Version:  2.0.40 2.2.26 2.4.37 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15 3.16 3.17 3.18

Linux/drivers/platform/x86/eeepc-laptop.c

  1 /*
  2  *  eeepc-laptop.c - Asus Eee PC extras
  3  *
  4  *  Based on asus_acpi.c as patched for the Eee PC by Asus:
  5  *  ftp://ftp.asus.com/pub/ASUS/EeePC/701/ASUS_ACPI_071126.rar
  6  *  Based on eee.c from eeepc-linux
  7  *
  8  *  This program is free software; you can redistribute it and/or modify
  9  *  it under the terms of the GNU General Public License as published by
 10  *  the Free Software Foundation; either version 2 of the License, or
 11  *  (at your option) any later version.
 12  *
 13  *  This program is distributed in the hope that it will be useful,
 14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 16  *  GNU General Public License for more details.
 17  */
 18 
 19 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 20 
 21 #include <linux/kernel.h>
 22 #include <linux/module.h>
 23 #include <linux/init.h>
 24 #include <linux/types.h>
 25 #include <linux/platform_device.h>
 26 #include <linux/backlight.h>
 27 #include <linux/fb.h>
 28 #include <linux/hwmon.h>
 29 #include <linux/hwmon-sysfs.h>
 30 #include <linux/slab.h>
 31 #include <linux/acpi.h>
 32 #include <linux/uaccess.h>
 33 #include <linux/input.h>
 34 #include <linux/input/sparse-keymap.h>
 35 #include <linux/rfkill.h>
 36 #include <linux/pci.h>
 37 #include <linux/pci_hotplug.h>
 38 #include <linux/leds.h>
 39 #include <linux/dmi.h>
 40 
 41 #define EEEPC_LAPTOP_VERSION    "0.1"
 42 #define EEEPC_LAPTOP_NAME       "Eee PC Hotkey Driver"
 43 #define EEEPC_LAPTOP_FILE       "eeepc"
 44 
 45 #define EEEPC_ACPI_CLASS        "hotkey"
 46 #define EEEPC_ACPI_DEVICE_NAME  "Hotkey"
 47 #define EEEPC_ACPI_HID          "ASUS010"
 48 
 49 MODULE_AUTHOR("Corentin Chary, Eric Cooper");
 50 MODULE_DESCRIPTION(EEEPC_LAPTOP_NAME);
 51 MODULE_LICENSE("GPL");
 52 
 53 static bool hotplug_disabled;
 54 
 55 module_param(hotplug_disabled, bool, 0444);
 56 MODULE_PARM_DESC(hotplug_disabled,
 57                  "Disable hotplug for wireless device. "
 58                  "If your laptop need that, please report to "
 59                  "acpi4asus-user@lists.sourceforge.net.");
 60 
 61 /*
 62  * Definitions for Asus EeePC
 63  */
 64 #define NOTIFY_BRN_MIN  0x20
 65 #define NOTIFY_BRN_MAX  0x2f
 66 
 67 enum {
 68         DISABLE_ASL_WLAN = 0x0001,
 69         DISABLE_ASL_BLUETOOTH = 0x0002,
 70         DISABLE_ASL_IRDA = 0x0004,
 71         DISABLE_ASL_CAMERA = 0x0008,
 72         DISABLE_ASL_TV = 0x0010,
 73         DISABLE_ASL_GPS = 0x0020,
 74         DISABLE_ASL_DISPLAYSWITCH = 0x0040,
 75         DISABLE_ASL_MODEM = 0x0080,
 76         DISABLE_ASL_CARDREADER = 0x0100,
 77         DISABLE_ASL_3G = 0x0200,
 78         DISABLE_ASL_WIMAX = 0x0400,
 79         DISABLE_ASL_HWCF = 0x0800
 80 };
 81 
 82 enum {
 83         CM_ASL_WLAN = 0,
 84         CM_ASL_BLUETOOTH,
 85         CM_ASL_IRDA,
 86         CM_ASL_1394,
 87         CM_ASL_CAMERA,
 88         CM_ASL_TV,
 89         CM_ASL_GPS,
 90         CM_ASL_DVDROM,
 91         CM_ASL_DISPLAYSWITCH,
 92         CM_ASL_PANELBRIGHT,
 93         CM_ASL_BIOSFLASH,
 94         CM_ASL_ACPIFLASH,
 95         CM_ASL_CPUFV,
 96         CM_ASL_CPUTEMPERATURE,
 97         CM_ASL_FANCPU,
 98         CM_ASL_FANCHASSIS,
 99         CM_ASL_USBPORT1,
100         CM_ASL_USBPORT2,
101         CM_ASL_USBPORT3,
102         CM_ASL_MODEM,
103         CM_ASL_CARDREADER,
104         CM_ASL_3G,
105         CM_ASL_WIMAX,
106         CM_ASL_HWCF,
107         CM_ASL_LID,
108         CM_ASL_TYPE,
109         CM_ASL_PANELPOWER,      /*P901*/
110         CM_ASL_TPD
111 };
112 
113 static const char *cm_getv[] = {
114         "WLDG", "BTHG", NULL, NULL,
115         "CAMG", NULL, NULL, NULL,
116         NULL, "PBLG", NULL, NULL,
117         "CFVG", NULL, NULL, NULL,
118         "USBG", NULL, NULL, "MODG",
119         "CRDG", "M3GG", "WIMG", "HWCF",
120         "LIDG", "TYPE", "PBPG", "TPDG"
121 };
122 
123 static const char *cm_setv[] = {
124         "WLDS", "BTHS", NULL, NULL,
125         "CAMS", NULL, NULL, NULL,
126         "SDSP", "PBLS", "HDPS", NULL,
127         "CFVS", NULL, NULL, NULL,
128         "USBG", NULL, NULL, "MODS",
129         "CRDS", "M3GS", "WIMS", NULL,
130         NULL, NULL, "PBPS", "TPDS"
131 };
132 
133 static const struct key_entry eeepc_keymap[] = {
134         { KE_KEY, 0x10, { KEY_WLAN } },
135         { KE_KEY, 0x11, { KEY_WLAN } },
136         { KE_KEY, 0x12, { KEY_PROG1 } },
137         { KE_KEY, 0x13, { KEY_MUTE } },
138         { KE_KEY, 0x14, { KEY_VOLUMEDOWN } },
139         { KE_KEY, 0x15, { KEY_VOLUMEUP } },
140         { KE_KEY, 0x16, { KEY_DISPLAY_OFF } },
141         { KE_KEY, 0x1a, { KEY_COFFEE } },
142         { KE_KEY, 0x1b, { KEY_ZOOM } },
143         { KE_KEY, 0x1c, { KEY_PROG2 } },
144         { KE_KEY, 0x1d, { KEY_PROG3 } },
145         { KE_KEY, NOTIFY_BRN_MIN, { KEY_BRIGHTNESSDOWN } },
146         { KE_KEY, NOTIFY_BRN_MAX, { KEY_BRIGHTNESSUP } },
147         { KE_KEY, 0x30, { KEY_SWITCHVIDEOMODE } },
148         { KE_KEY, 0x31, { KEY_SWITCHVIDEOMODE } },
149         { KE_KEY, 0x32, { KEY_SWITCHVIDEOMODE } },
150         { KE_KEY, 0x37, { KEY_F13 } }, /* Disable Touchpad */
151         { KE_KEY, 0x38, { KEY_F14 } },
152         { KE_END, 0 },
153 };
154 
155 /*
156  * This is the main structure, we can use it to store useful information
157  */
158 struct eeepc_laptop {
159         acpi_handle handle;             /* the handle of the acpi device */
160         u32 cm_supported;               /* the control methods supported
161                                            by this BIOS */
162         bool cpufv_disabled;
163         bool hotplug_disabled;
164         u16 event_count[128];           /* count for each event */
165 
166         struct platform_device *platform_device;
167         struct acpi_device *device;             /* the device we are in */
168         struct backlight_device *backlight_device;
169 
170         struct input_dev *inputdev;
171 
172         struct rfkill *wlan_rfkill;
173         struct rfkill *bluetooth_rfkill;
174         struct rfkill *wwan3g_rfkill;
175         struct rfkill *wimax_rfkill;
176 
177         struct hotplug_slot *hotplug_slot;
178         struct mutex hotplug_lock;
179 
180         struct led_classdev tpd_led;
181         int tpd_led_wk;
182         struct workqueue_struct *led_workqueue;
183         struct work_struct tpd_led_work;
184 };
185 
186 /*
187  * ACPI Helpers
188  */
189 static int write_acpi_int(acpi_handle handle, const char *method, int val)
190 {
191         acpi_status status;
192 
193         status = acpi_execute_simple_method(handle, (char *)method, val);
194 
195         return (status == AE_OK ? 0 : -1);
196 }
197 
198 static int read_acpi_int(acpi_handle handle, const char *method, int *val)
199 {
200         acpi_status status;
201         unsigned long long result;
202 
203         status = acpi_evaluate_integer(handle, (char *)method, NULL, &result);
204         if (ACPI_FAILURE(status)) {
205                 *val = -1;
206                 return -1;
207         } else {
208                 *val = result;
209                 return 0;
210         }
211 }
212 
213 static int set_acpi(struct eeepc_laptop *eeepc, int cm, int value)
214 {
215         const char *method = cm_setv[cm];
216 
217         if (method == NULL)
218                 return -ENODEV;
219         if ((eeepc->cm_supported & (0x1 << cm)) == 0)
220                 return -ENODEV;
221 
222         if (write_acpi_int(eeepc->handle, method, value))
223                 pr_warn("Error writing %s\n", method);
224         return 0;
225 }
226 
227 static int get_acpi(struct eeepc_laptop *eeepc, int cm)
228 {
229         const char *method = cm_getv[cm];
230         int value;
231 
232         if (method == NULL)
233                 return -ENODEV;
234         if ((eeepc->cm_supported & (0x1 << cm)) == 0)
235                 return -ENODEV;
236 
237         if (read_acpi_int(eeepc->handle, method, &value))
238                 pr_warn("Error reading %s\n", method);
239         return value;
240 }
241 
242 static int acpi_setter_handle(struct eeepc_laptop *eeepc, int cm,
243                               acpi_handle *handle)
244 {
245         const char *method = cm_setv[cm];
246         acpi_status status;
247 
248         if (method == NULL)
249                 return -ENODEV;
250         if ((eeepc->cm_supported & (0x1 << cm)) == 0)
251                 return -ENODEV;
252 
253         status = acpi_get_handle(eeepc->handle, (char *)method,
254                                  handle);
255         if (status != AE_OK) {
256                 pr_warn("Error finding %s\n", method);
257                 return -ENODEV;
258         }
259         return 0;
260 }
261 
262 
263 /*
264  * Sys helpers
265  */
266 static int parse_arg(const char *buf, int *val)
267 {
268         if (sscanf(buf, "%i", val) != 1)
269                 return -EINVAL;
270         return 0;
271 }
272 
273 static ssize_t store_sys_acpi(struct device *dev, int cm,
274                               const char *buf, size_t count)
275 {
276         struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
277         int rv, value;
278 
279         rv = parse_arg(buf, &value);
280         if (rv < 0)
281                 return rv;
282         rv = set_acpi(eeepc, cm, value);
283         if (rv < 0)
284                 return -EIO;
285         return count;
286 }
287 
288 static ssize_t show_sys_acpi(struct device *dev, int cm, char *buf)
289 {
290         struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
291         int value = get_acpi(eeepc, cm);
292 
293         if (value < 0)
294                 return -EIO;
295         return sprintf(buf, "%d\n", value);
296 }
297 
298 #define EEEPC_ACPI_SHOW_FUNC(_name, _cm)                                \
299         static ssize_t _name##_show(struct device *dev,                 \
300                                     struct device_attribute *attr,      \
301                                     char *buf)                          \
302         {                                                               \
303                 return show_sys_acpi(dev, _cm, buf);                    \
304         }
305 
306 #define EEEPC_ACPI_STORE_FUNC(_name, _cm)                               \
307         static ssize_t _name##_store(struct device *dev,                \
308                                      struct device_attribute *attr,     \
309                                      const char *buf, size_t count)     \
310         {                                                               \
311                 return store_sys_acpi(dev, _cm, buf, count);            \
312         }
313 
314 #define EEEPC_CREATE_DEVICE_ATTR_RW(_name, _cm)                         \
315         EEEPC_ACPI_SHOW_FUNC(_name, _cm)                                \
316         EEEPC_ACPI_STORE_FUNC(_name, _cm)                               \
317         static DEVICE_ATTR_RW(_name)
318 
319 #define EEEPC_CREATE_DEVICE_ATTR_WO(_name, _cm)                         \
320         EEEPC_ACPI_STORE_FUNC(_name, _cm)                               \
321         static DEVICE_ATTR_WO(_name)
322 
323 EEEPC_CREATE_DEVICE_ATTR_RW(camera, CM_ASL_CAMERA);
324 EEEPC_CREATE_DEVICE_ATTR_RW(cardr, CM_ASL_CARDREADER);
325 EEEPC_CREATE_DEVICE_ATTR_WO(disp, CM_ASL_DISPLAYSWITCH);
326 
327 struct eeepc_cpufv {
328         int num;
329         int cur;
330 };
331 
332 static int get_cpufv(struct eeepc_laptop *eeepc, struct eeepc_cpufv *c)
333 {
334         c->cur = get_acpi(eeepc, CM_ASL_CPUFV);
335         if (c->cur < 0)
336                 return -ENODEV;
337 
338         c->num = (c->cur >> 8) & 0xff;
339         c->cur &= 0xff;
340         if (c->num == 0 || c->num > 12)
341                 return -ENODEV;
342         return 0;
343 }
344 
345 static ssize_t available_cpufv_show(struct device *dev,
346                                     struct device_attribute *attr,
347                                     char *buf)
348 {
349         struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
350         struct eeepc_cpufv c;
351         int i;
352         ssize_t len = 0;
353 
354         if (get_cpufv(eeepc, &c))
355                 return -ENODEV;
356         for (i = 0; i < c.num; i++)
357                 len += sprintf(buf + len, "%d ", i);
358         len += sprintf(buf + len, "\n");
359         return len;
360 }
361 
362 static ssize_t cpufv_show(struct device *dev,
363                           struct device_attribute *attr,
364                           char *buf)
365 {
366         struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
367         struct eeepc_cpufv c;
368 
369         if (get_cpufv(eeepc, &c))
370                 return -ENODEV;
371         return sprintf(buf, "%#x\n", (c.num << 8) | c.cur);
372 }
373 
374 static ssize_t cpufv_store(struct device *dev,
375                            struct device_attribute *attr,
376                            const char *buf, size_t count)
377 {
378         struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
379         struct eeepc_cpufv c;
380         int rv, value;
381 
382         if (eeepc->cpufv_disabled)
383                 return -EPERM;
384         if (get_cpufv(eeepc, &c))
385                 return -ENODEV;
386         rv = parse_arg(buf, &value);
387         if (rv < 0)
388                 return rv;
389         if (value < 0 || value >= c.num)
390                 return -EINVAL;
391         rv = set_acpi(eeepc, CM_ASL_CPUFV, value);
392         if (rv)
393                 return rv;
394         return count;
395 }
396 
397 static ssize_t cpufv_disabled_show(struct device *dev,
398                           struct device_attribute *attr,
399                           char *buf)
400 {
401         struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
402 
403         return sprintf(buf, "%d\n", eeepc->cpufv_disabled);
404 }
405 
406 static ssize_t cpufv_disabled_store(struct device *dev,
407                            struct device_attribute *attr,
408                            const char *buf, size_t count)
409 {
410         struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
411         int rv, value;
412 
413         rv = parse_arg(buf, &value);
414         if (rv < 0)
415                 return rv;
416 
417         switch (value) {
418         case 0:
419                 if (eeepc->cpufv_disabled)
420                         pr_warn("cpufv enabled (not officially supported "
421                                 "on this model)\n");
422                 eeepc->cpufv_disabled = false;
423                 return count;
424         case 1:
425                 return -EPERM;
426         default:
427                 return -EINVAL;
428         }
429 }
430 
431 
432 static DEVICE_ATTR_RW(cpufv);
433 static DEVICE_ATTR_RO(available_cpufv);
434 static DEVICE_ATTR_RW(cpufv_disabled);
435 
436 static struct attribute *platform_attributes[] = {
437         &dev_attr_camera.attr,
438         &dev_attr_cardr.attr,
439         &dev_attr_disp.attr,
440         &dev_attr_cpufv.attr,
441         &dev_attr_available_cpufv.attr,
442         &dev_attr_cpufv_disabled.attr,
443         NULL
444 };
445 
446 static struct attribute_group platform_attribute_group = {
447         .attrs = platform_attributes
448 };
449 
450 static int eeepc_platform_init(struct eeepc_laptop *eeepc)
451 {
452         int result;
453 
454         eeepc->platform_device = platform_device_alloc(EEEPC_LAPTOP_FILE, -1);
455         if (!eeepc->platform_device)
456                 return -ENOMEM;
457         platform_set_drvdata(eeepc->platform_device, eeepc);
458 
459         result = platform_device_add(eeepc->platform_device);
460         if (result)
461                 goto fail_platform_device;
462 
463         result = sysfs_create_group(&eeepc->platform_device->dev.kobj,
464                                     &platform_attribute_group);
465         if (result)
466                 goto fail_sysfs;
467         return 0;
468 
469 fail_sysfs:
470         platform_device_del(eeepc->platform_device);
471 fail_platform_device:
472         platform_device_put(eeepc->platform_device);
473         return result;
474 }
475 
476 static void eeepc_platform_exit(struct eeepc_laptop *eeepc)
477 {
478         sysfs_remove_group(&eeepc->platform_device->dev.kobj,
479                            &platform_attribute_group);
480         platform_device_unregister(eeepc->platform_device);
481 }
482 
483 /*
484  * LEDs
485  */
486 /*
487  * These functions actually update the LED's, and are called from a
488  * workqueue. By doing this as separate work rather than when the LED
489  * subsystem asks, we avoid messing with the Asus ACPI stuff during a
490  * potentially bad time, such as a timer interrupt.
491  */
492 static void tpd_led_update(struct work_struct *work)
493  {
494         struct eeepc_laptop *eeepc;
495 
496         eeepc = container_of(work, struct eeepc_laptop, tpd_led_work);
497 
498         set_acpi(eeepc, CM_ASL_TPD, eeepc->tpd_led_wk);
499 }
500 
501 static void tpd_led_set(struct led_classdev *led_cdev,
502                         enum led_brightness value)
503 {
504         struct eeepc_laptop *eeepc;
505 
506         eeepc = container_of(led_cdev, struct eeepc_laptop, tpd_led);
507 
508         eeepc->tpd_led_wk = (value > 0) ? 1 : 0;
509         queue_work(eeepc->led_workqueue, &eeepc->tpd_led_work);
510 }
511 
512 static enum led_brightness tpd_led_get(struct led_classdev *led_cdev)
513 {
514         struct eeepc_laptop *eeepc;
515 
516         eeepc = container_of(led_cdev, struct eeepc_laptop, tpd_led);
517 
518         return get_acpi(eeepc, CM_ASL_TPD);
519 }
520 
521 static int eeepc_led_init(struct eeepc_laptop *eeepc)
522 {
523         int rv;
524 
525         if (get_acpi(eeepc, CM_ASL_TPD) == -ENODEV)
526                 return 0;
527 
528         eeepc->led_workqueue = create_singlethread_workqueue("led_workqueue");
529         if (!eeepc->led_workqueue)
530                 return -ENOMEM;
531         INIT_WORK(&eeepc->tpd_led_work, tpd_led_update);
532 
533         eeepc->tpd_led.name = "eeepc::touchpad";
534         eeepc->tpd_led.brightness_set = tpd_led_set;
535         if (get_acpi(eeepc, CM_ASL_TPD) >= 0) /* if method is available */
536                 eeepc->tpd_led.brightness_get = tpd_led_get;
537         eeepc->tpd_led.max_brightness = 1;
538 
539         rv = led_classdev_register(&eeepc->platform_device->dev,
540                                    &eeepc->tpd_led);
541         if (rv) {
542                 destroy_workqueue(eeepc->led_workqueue);
543                 return rv;
544         }
545 
546         return 0;
547 }
548 
549 static void eeepc_led_exit(struct eeepc_laptop *eeepc)
550 {
551         if (!IS_ERR_OR_NULL(eeepc->tpd_led.dev))
552                 led_classdev_unregister(&eeepc->tpd_led);
553         if (eeepc->led_workqueue)
554                 destroy_workqueue(eeepc->led_workqueue);
555 }
556 
557 
558 /*
559  * PCI hotplug (for wlan rfkill)
560  */
561 static bool eeepc_wlan_rfkill_blocked(struct eeepc_laptop *eeepc)
562 {
563         if (get_acpi(eeepc, CM_ASL_WLAN) == 1)
564                 return false;
565         return true;
566 }
567 
568 static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc, acpi_handle handle)
569 {
570         struct pci_dev *port;
571         struct pci_dev *dev;
572         struct pci_bus *bus;
573         bool blocked = eeepc_wlan_rfkill_blocked(eeepc);
574         bool absent;
575         u32 l;
576 
577         if (eeepc->wlan_rfkill)
578                 rfkill_set_sw_state(eeepc->wlan_rfkill, blocked);
579 
580         mutex_lock(&eeepc->hotplug_lock);
581         pci_lock_rescan_remove();
582 
583         if (eeepc->hotplug_slot) {
584                 port = acpi_get_pci_dev(handle);
585                 if (!port) {
586                         pr_warning("Unable to find port\n");
587                         goto out_unlock;
588                 }
589 
590                 bus = port->subordinate;
591 
592                 if (!bus) {
593                         pr_warn("Unable to find PCI bus 1?\n");
594                         goto out_put_dev;
595                 }
596 
597                 if (pci_bus_read_config_dword(bus, 0, PCI_VENDOR_ID, &l)) {
598                         pr_err("Unable to read PCI config space?\n");
599                         goto out_put_dev;
600                 }
601 
602                 absent = (l == 0xffffffff);
603 
604                 if (blocked != absent) {
605                         pr_warn("BIOS says wireless lan is %s, "
606                                 "but the pci device is %s\n",
607                                 blocked ? "blocked" : "unblocked",
608                                 absent ? "absent" : "present");
609                         pr_warn("skipped wireless hotplug as probably "
610                                 "inappropriate for this model\n");
611                         goto out_put_dev;
612                 }
613 
614                 if (!blocked) {
615                         dev = pci_get_slot(bus, 0);
616                         if (dev) {
617                                 /* Device already present */
618                                 pci_dev_put(dev);
619                                 goto out_put_dev;
620                         }
621                         dev = pci_scan_single_device(bus, 0);
622                         if (dev) {
623                                 pci_bus_assign_resources(bus);
624                                 pci_bus_add_device(dev);
625                         }
626                 } else {
627                         dev = pci_get_slot(bus, 0);
628                         if (dev) {
629                                 pci_stop_and_remove_bus_device(dev);
630                                 pci_dev_put(dev);
631                         }
632                 }
633 out_put_dev:
634                 pci_dev_put(port);
635         }
636 
637 out_unlock:
638         pci_unlock_rescan_remove();
639         mutex_unlock(&eeepc->hotplug_lock);
640 }
641 
642 static void eeepc_rfkill_hotplug_update(struct eeepc_laptop *eeepc, char *node)
643 {
644         acpi_status status = AE_OK;
645         acpi_handle handle;
646 
647         status = acpi_get_handle(NULL, node, &handle);
648 
649         if (ACPI_SUCCESS(status))
650                 eeepc_rfkill_hotplug(eeepc, handle);
651 }
652 
653 static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
654 {
655         struct eeepc_laptop *eeepc = data;
656 
657         if (event != ACPI_NOTIFY_BUS_CHECK)
658                 return;
659 
660         eeepc_rfkill_hotplug(eeepc, handle);
661 }
662 
663 static int eeepc_register_rfkill_notifier(struct eeepc_laptop *eeepc,
664                                           char *node)
665 {
666         acpi_status status;
667         acpi_handle handle;
668 
669         status = acpi_get_handle(NULL, node, &handle);
670 
671         if (ACPI_FAILURE(status))
672                 return -ENODEV;
673 
674         status = acpi_install_notify_handler(handle,
675                                              ACPI_SYSTEM_NOTIFY,
676                                              eeepc_rfkill_notify,
677                                              eeepc);
678         if (ACPI_FAILURE(status))
679                 pr_warn("Failed to register notify on %s\n", node);
680 
681         /*
682          * Refresh pci hotplug in case the rfkill state was
683          * changed during setup.
684          */
685         eeepc_rfkill_hotplug(eeepc, handle);
686         return 0;
687 }
688 
689 static void eeepc_unregister_rfkill_notifier(struct eeepc_laptop *eeepc,
690                                              char *node)
691 {
692         acpi_status status = AE_OK;
693         acpi_handle handle;
694 
695         status = acpi_get_handle(NULL, node, &handle);
696 
697         if (ACPI_FAILURE(status))
698                 return;
699 
700         status = acpi_remove_notify_handler(handle,
701                                              ACPI_SYSTEM_NOTIFY,
702                                              eeepc_rfkill_notify);
703         if (ACPI_FAILURE(status))
704                 pr_err("Error removing rfkill notify handler %s\n",
705                         node);
706                 /*
707                  * Refresh pci hotplug in case the rfkill
708                  * state was changed after
709                  * eeepc_unregister_rfkill_notifier()
710                  */
711         eeepc_rfkill_hotplug(eeepc, handle);
712 }
713 
714 static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot,
715                                     u8 *value)
716 {
717         struct eeepc_laptop *eeepc = hotplug_slot->private;
718         int val = get_acpi(eeepc, CM_ASL_WLAN);
719 
720         if (val == 1 || val == 0)
721                 *value = val;
722         else
723                 return -EINVAL;
724 
725         return 0;
726 }
727 
728 static void eeepc_cleanup_pci_hotplug(struct hotplug_slot *hotplug_slot)
729 {
730         kfree(hotplug_slot->info);
731         kfree(hotplug_slot);
732 }
733 
734 static struct hotplug_slot_ops eeepc_hotplug_slot_ops = {
735         .owner = THIS_MODULE,
736         .get_adapter_status = eeepc_get_adapter_status,
737         .get_power_status = eeepc_get_adapter_status,
738 };
739 
740 static int eeepc_setup_pci_hotplug(struct eeepc_laptop *eeepc)
741 {
742         int ret = -ENOMEM;
743         struct pci_bus *bus = pci_find_bus(0, 1);
744 
745         if (!bus) {
746                 pr_err("Unable to find wifi PCI bus\n");
747                 return -ENODEV;
748         }
749 
750         eeepc->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
751         if (!eeepc->hotplug_slot)
752                 goto error_slot;
753 
754         eeepc->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info),
755                                             GFP_KERNEL);
756         if (!eeepc->hotplug_slot->info)
757                 goto error_info;
758 
759         eeepc->hotplug_slot->private = eeepc;
760         eeepc->hotplug_slot->release = &eeepc_cleanup_pci_hotplug;
761         eeepc->hotplug_slot->ops = &eeepc_hotplug_slot_ops;
762         eeepc_get_adapter_status(eeepc->hotplug_slot,
763                                  &eeepc->hotplug_slot->info->adapter_status);
764 
765         ret = pci_hp_register(eeepc->hotplug_slot, bus, 0, "eeepc-wifi");
766         if (ret) {
767                 pr_err("Unable to register hotplug slot - %d\n", ret);
768                 goto error_register;
769         }
770 
771         return 0;
772 
773 error_register:
774         kfree(eeepc->hotplug_slot->info);
775 error_info:
776         kfree(eeepc->hotplug_slot);
777         eeepc->hotplug_slot = NULL;
778 error_slot:
779         return ret;
780 }
781 
782 /*
783  * Rfkill devices
784  */
785 static int eeepc_rfkill_set(void *data, bool blocked)
786 {
787         acpi_handle handle = data;
788 
789         return write_acpi_int(handle, NULL, !blocked);
790 }
791 
792 static const struct rfkill_ops eeepc_rfkill_ops = {
793         .set_block = eeepc_rfkill_set,
794 };
795 
796 static int eeepc_new_rfkill(struct eeepc_laptop *eeepc,
797                             struct rfkill **rfkill,
798                             const char *name,
799                             enum rfkill_type type, int cm)
800 {
801         acpi_handle handle;
802         int result;
803 
804         result = acpi_setter_handle(eeepc, cm, &handle);
805         if (result < 0)
806                 return result;
807 
808         *rfkill = rfkill_alloc(name, &eeepc->platform_device->dev, type,
809                                &eeepc_rfkill_ops, handle);
810 
811         if (!*rfkill)
812                 return -EINVAL;
813 
814         rfkill_init_sw_state(*rfkill, get_acpi(eeepc, cm) != 1);
815         result = rfkill_register(*rfkill);
816         if (result) {
817                 rfkill_destroy(*rfkill);
818                 *rfkill = NULL;
819                 return result;
820         }
821         return 0;
822 }
823 
824 static void eeepc_rfkill_exit(struct eeepc_laptop *eeepc)
825 {
826         eeepc_unregister_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P5");
827         eeepc_unregister_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P6");
828         eeepc_unregister_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P7");
829         if (eeepc->wlan_rfkill) {
830                 rfkill_unregister(eeepc->wlan_rfkill);
831                 rfkill_destroy(eeepc->wlan_rfkill);
832                 eeepc->wlan_rfkill = NULL;
833         }
834 
835         if (eeepc->hotplug_slot)
836                 pci_hp_deregister(eeepc->hotplug_slot);
837 
838         if (eeepc->bluetooth_rfkill) {
839                 rfkill_unregister(eeepc->bluetooth_rfkill);
840                 rfkill_destroy(eeepc->bluetooth_rfkill);
841                 eeepc->bluetooth_rfkill = NULL;
842         }
843         if (eeepc->wwan3g_rfkill) {
844                 rfkill_unregister(eeepc->wwan3g_rfkill);
845                 rfkill_destroy(eeepc->wwan3g_rfkill);
846                 eeepc->wwan3g_rfkill = NULL;
847         }
848         if (eeepc->wimax_rfkill) {
849                 rfkill_unregister(eeepc->wimax_rfkill);
850                 rfkill_destroy(eeepc->wimax_rfkill);
851                 eeepc->wimax_rfkill = NULL;
852         }
853 }
854 
855 static int eeepc_rfkill_init(struct eeepc_laptop *eeepc)
856 {
857         int result = 0;
858 
859         mutex_init(&eeepc->hotplug_lock);
860 
861         result = eeepc_new_rfkill(eeepc, &eeepc->wlan_rfkill,
862                                   "eeepc-wlan", RFKILL_TYPE_WLAN,
863                                   CM_ASL_WLAN);
864 
865         if (result && result != -ENODEV)
866                 goto exit;
867 
868         result = eeepc_new_rfkill(eeepc, &eeepc->bluetooth_rfkill,
869                                   "eeepc-bluetooth", RFKILL_TYPE_BLUETOOTH,
870                                   CM_ASL_BLUETOOTH);
871 
872         if (result && result != -ENODEV)
873                 goto exit;
874 
875         result = eeepc_new_rfkill(eeepc, &eeepc->wwan3g_rfkill,
876                                   "eeepc-wwan3g", RFKILL_TYPE_WWAN,
877                                   CM_ASL_3G);
878 
879         if (result && result != -ENODEV)
880                 goto exit;
881 
882         result = eeepc_new_rfkill(eeepc, &eeepc->wimax_rfkill,
883                                   "eeepc-wimax", RFKILL_TYPE_WIMAX,
884                                   CM_ASL_WIMAX);
885 
886         if (result && result != -ENODEV)
887                 goto exit;
888 
889         if (eeepc->hotplug_disabled)
890                 return 0;
891 
892         result = eeepc_setup_pci_hotplug(eeepc);
893         /*
894          * If we get -EBUSY then something else is handling the PCI hotplug -
895          * don't fail in this case
896          */
897         if (result == -EBUSY)
898                 result = 0;
899 
900         eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P5");
901         eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P6");
902         eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P7");
903 
904 exit:
905         if (result && result != -ENODEV)
906                 eeepc_rfkill_exit(eeepc);
907         return result;
908 }
909 
910 /*
911  * Platform driver - hibernate/resume callbacks
912  */
913 static int eeepc_hotk_thaw(struct device *device)
914 {
915         struct eeepc_laptop *eeepc = dev_get_drvdata(device);
916 
917         if (eeepc->wlan_rfkill) {
918                 bool wlan;
919 
920                 /*
921                  * Work around bios bug - acpi _PTS turns off the wireless led
922                  * during suspend.  Normally it restores it on resume, but
923                  * we should kick it ourselves in case hibernation is aborted.
924                  */
925                 wlan = get_acpi(eeepc, CM_ASL_WLAN);
926                 set_acpi(eeepc, CM_ASL_WLAN, wlan);
927         }
928 
929         return 0;
930 }
931 
932 static int eeepc_hotk_restore(struct device *device)
933 {
934         struct eeepc_laptop *eeepc = dev_get_drvdata(device);
935 
936         /* Refresh both wlan rfkill state and pci hotplug */
937         if (eeepc->wlan_rfkill) {
938                 eeepc_rfkill_hotplug_update(eeepc, "\\_SB.PCI0.P0P5");
939                 eeepc_rfkill_hotplug_update(eeepc, "\\_SB.PCI0.P0P6");
940                 eeepc_rfkill_hotplug_update(eeepc, "\\_SB.PCI0.P0P7");
941         }
942 
943         if (eeepc->bluetooth_rfkill)
944                 rfkill_set_sw_state(eeepc->bluetooth_rfkill,
945                                     get_acpi(eeepc, CM_ASL_BLUETOOTH) != 1);
946         if (eeepc->wwan3g_rfkill)
947                 rfkill_set_sw_state(eeepc->wwan3g_rfkill,
948                                     get_acpi(eeepc, CM_ASL_3G) != 1);
949         if (eeepc->wimax_rfkill)
950                 rfkill_set_sw_state(eeepc->wimax_rfkill,
951                                     get_acpi(eeepc, CM_ASL_WIMAX) != 1);
952 
953         return 0;
954 }
955 
956 static const struct dev_pm_ops eeepc_pm_ops = {
957         .thaw = eeepc_hotk_thaw,
958         .restore = eeepc_hotk_restore,
959 };
960 
961 static struct platform_driver platform_driver = {
962         .driver = {
963                 .name = EEEPC_LAPTOP_FILE,
964                 .owner = THIS_MODULE,
965                 .pm = &eeepc_pm_ops,
966         }
967 };
968 
969 /*
970  * Hwmon device
971  */
972 
973 #define EEEPC_EC_SC00      0x61
974 #define EEEPC_EC_FAN_PWM   (EEEPC_EC_SC00 + 2) /* Fan PWM duty cycle (%) */
975 #define EEEPC_EC_FAN_HRPM  (EEEPC_EC_SC00 + 5) /* High byte, fan speed (RPM) */
976 #define EEEPC_EC_FAN_LRPM  (EEEPC_EC_SC00 + 6) /* Low byte, fan speed (RPM) */
977 
978 #define EEEPC_EC_SFB0      0xD0
979 #define EEEPC_EC_FAN_CTRL  (EEEPC_EC_SFB0 + 3) /* Byte containing SF25  */
980 
981 static int eeepc_get_fan_pwm(void)
982 {
983         u8 value = 0;
984 
985         ec_read(EEEPC_EC_FAN_PWM, &value);
986         return value * 255 / 100;
987 }
988 
989 static void eeepc_set_fan_pwm(int value)
990 {
991         value = clamp_val(value, 0, 255);
992         value = value * 100 / 255;
993         ec_write(EEEPC_EC_FAN_PWM, value);
994 }
995 
996 static int eeepc_get_fan_rpm(void)
997 {
998         u8 high = 0;
999         u8 low = 0;
1000 
1001         ec_read(EEEPC_EC_FAN_HRPM, &high);
1002         ec_read(EEEPC_EC_FAN_LRPM, &low);
1003         return high << 8 | low;
1004 }
1005 
1006 static int eeepc_get_fan_ctrl(void)
1007 {
1008         u8 value = 0;
1009 
1010         ec_read(EEEPC_EC_FAN_CTRL, &value);
1011         if (value & 0x02)
1012                 return 1; /* manual */
1013         else
1014                 return 2; /* automatic */
1015 }
1016 
1017 static void eeepc_set_fan_ctrl(int manual)
1018 {
1019         u8 value = 0;
1020 
1021         ec_read(EEEPC_EC_FAN_CTRL, &value);
1022         if (manual == 1)
1023                 value |= 0x02;
1024         else
1025                 value &= ~0x02;
1026         ec_write(EEEPC_EC_FAN_CTRL, value);
1027 }
1028 
1029 static ssize_t store_sys_hwmon(void (*set)(int), const char *buf, size_t count)
1030 {
1031         int rv, value;
1032 
1033         rv = parse_arg(buf, &value);
1034         if (rv < 0)
1035                 return rv;
1036         set(value);
1037         return count;
1038 }
1039 
1040 static ssize_t show_sys_hwmon(int (*get)(void), char *buf)
1041 {
1042         return sprintf(buf, "%d\n", get());
1043 }
1044 
1045 #define EEEPC_SENSOR_SHOW_FUNC(_name, _get)                             \
1046         static ssize_t _name##_show(struct device *dev,                 \
1047                                     struct device_attribute *attr,      \
1048                                     char *buf)                          \
1049         {                                                               \
1050                 return show_sys_hwmon(_get, buf);                       \
1051         }
1052 
1053 #define EEEPC_SENSOR_STORE_FUNC(_name, _set)                            \
1054         static ssize_t _name##_store(struct device *dev,                \
1055                                      struct device_attribute *attr,     \
1056                                      const char *buf, size_t count)     \
1057         {                                                               \
1058                 return store_sys_hwmon(_set, buf, count);               \
1059         }
1060 
1061 #define EEEPC_CREATE_SENSOR_ATTR_RW(_name, _get, _set)                  \
1062         EEEPC_SENSOR_SHOW_FUNC(_name, _get)                             \
1063         EEEPC_SENSOR_STORE_FUNC(_name, _set)                            \
1064         static DEVICE_ATTR_RW(_name)
1065 
1066 #define EEEPC_CREATE_SENSOR_ATTR_RO(_name, _get)                        \
1067         EEEPC_SENSOR_SHOW_FUNC(_name, _get)                             \
1068         static DEVICE_ATTR_RO(_name)
1069 
1070 EEEPC_CREATE_SENSOR_ATTR_RO(fan1_input, eeepc_get_fan_rpm);
1071 EEEPC_CREATE_SENSOR_ATTR_RW(pwm1, eeepc_get_fan_pwm,
1072                             eeepc_set_fan_pwm);
1073 EEEPC_CREATE_SENSOR_ATTR_RW(pwm1_enable, eeepc_get_fan_ctrl,
1074                             eeepc_set_fan_ctrl);
1075 
1076 static struct attribute *hwmon_attrs[] = {
1077         &dev_attr_pwm1.attr,
1078         &dev_attr_fan1_input.attr,
1079         &dev_attr_pwm1_enable.attr,
1080         NULL
1081 };
1082 ATTRIBUTE_GROUPS(hwmon);
1083 
1084 static int eeepc_hwmon_init(struct eeepc_laptop *eeepc)
1085 {
1086         struct device *dev = &eeepc->platform_device->dev;
1087         struct device *hwmon;
1088 
1089         hwmon = devm_hwmon_device_register_with_groups(dev, "eeepc", NULL,
1090                                                        hwmon_groups);
1091         if (IS_ERR(hwmon)) {
1092                 pr_err("Could not register eeepc hwmon device\n");
1093                 return PTR_ERR(hwmon);
1094         }
1095         return 0;
1096 }
1097 
1098 /*
1099  * Backlight device
1100  */
1101 static int read_brightness(struct backlight_device *bd)
1102 {
1103         struct eeepc_laptop *eeepc = bl_get_data(bd);
1104 
1105         return get_acpi(eeepc, CM_ASL_PANELBRIGHT);
1106 }
1107 
1108 static int set_brightness(struct backlight_device *bd, int value)
1109 {
1110         struct eeepc_laptop *eeepc = bl_get_data(bd);
1111 
1112         return set_acpi(eeepc, CM_ASL_PANELBRIGHT, value);
1113 }
1114 
1115 static int update_bl_status(struct backlight_device *bd)
1116 {
1117         return set_brightness(bd, bd->props.brightness);
1118 }
1119 
1120 static const struct backlight_ops eeepcbl_ops = {
1121         .get_brightness = read_brightness,
1122         .update_status = update_bl_status,
1123 };
1124 
1125 static int eeepc_backlight_notify(struct eeepc_laptop *eeepc)
1126 {
1127         struct backlight_device *bd = eeepc->backlight_device;
1128         int old = bd->props.brightness;
1129 
1130         backlight_force_update(bd, BACKLIGHT_UPDATE_HOTKEY);
1131 
1132         return old;
1133 }
1134 
1135 static int eeepc_backlight_init(struct eeepc_laptop *eeepc)
1136 {
1137         struct backlight_properties props;
1138         struct backlight_device *bd;
1139 
1140         memset(&props, 0, sizeof(struct backlight_properties));
1141         props.type = BACKLIGHT_PLATFORM;
1142         props.max_brightness = 15;
1143         bd = backlight_device_register(EEEPC_LAPTOP_FILE,
1144                                        &eeepc->platform_device->dev, eeepc,
1145                                        &eeepcbl_ops, &props);
1146         if (IS_ERR(bd)) {
1147                 pr_err("Could not register eeepc backlight device\n");
1148                 eeepc->backlight_device = NULL;
1149                 return PTR_ERR(bd);
1150         }
1151         eeepc->backlight_device = bd;
1152         bd->props.brightness = read_brightness(bd);
1153         bd->props.power = FB_BLANK_UNBLANK;
1154         backlight_update_status(bd);
1155         return 0;
1156 }
1157 
1158 static void eeepc_backlight_exit(struct eeepc_laptop *eeepc)
1159 {
1160         if (eeepc->backlight_device)
1161                 backlight_device_unregister(eeepc->backlight_device);
1162         eeepc->backlight_device = NULL;
1163 }
1164 
1165 
1166 /*
1167  * Input device (i.e. hotkeys)
1168  */
1169 static int eeepc_input_init(struct eeepc_laptop *eeepc)
1170 {
1171         struct input_dev *input;
1172         int error;
1173 
1174         input = input_allocate_device();
1175         if (!input)
1176                 return -ENOMEM;
1177 
1178         input->name = "Asus EeePC extra buttons";
1179         input->phys = EEEPC_LAPTOP_FILE "/input0";
1180         input->id.bustype = BUS_HOST;
1181         input->dev.parent = &eeepc->platform_device->dev;
1182 
1183         error = sparse_keymap_setup(input, eeepc_keymap, NULL);
1184         if (error) {
1185                 pr_err("Unable to setup input device keymap\n");
1186                 goto err_free_dev;
1187         }
1188 
1189         error = input_register_device(input);
1190         if (error) {
1191                 pr_err("Unable to register input device\n");
1192                 goto err_free_keymap;
1193         }
1194 
1195         eeepc->inputdev = input;
1196         return 0;
1197 
1198 err_free_keymap:
1199         sparse_keymap_free(input);
1200 err_free_dev:
1201         input_free_device(input);
1202         return error;
1203 }
1204 
1205 static void eeepc_input_exit(struct eeepc_laptop *eeepc)
1206 {
1207         if (eeepc->inputdev) {
1208                 sparse_keymap_free(eeepc->inputdev);
1209                 input_unregister_device(eeepc->inputdev);
1210         }
1211         eeepc->inputdev = NULL;
1212 }
1213 
1214 /*
1215  * ACPI driver
1216  */
1217 static void eeepc_input_notify(struct eeepc_laptop *eeepc, int event)
1218 {
1219         if (!eeepc->inputdev)
1220                 return ;
1221         if (!sparse_keymap_report_event(eeepc->inputdev, event, 1, true))
1222                 pr_info("Unknown key %x pressed\n", event);
1223 }
1224 
1225 static void eeepc_acpi_notify(struct acpi_device *device, u32 event)
1226 {
1227         struct eeepc_laptop *eeepc = acpi_driver_data(device);
1228         u16 count;
1229 
1230         if (event > ACPI_MAX_SYS_NOTIFY)
1231                 return;
1232         count = eeepc->event_count[event % 128]++;
1233         acpi_bus_generate_netlink_event(device->pnp.device_class,
1234                                         dev_name(&device->dev), event,
1235                                         count);
1236 
1237         /* Brightness events are special */
1238         if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX) {
1239 
1240                 /* Ignore them completely if the acpi video driver is used */
1241                 if (eeepc->backlight_device != NULL) {
1242                         int old_brightness, new_brightness;
1243 
1244                         /* Update the backlight device. */
1245                         old_brightness = eeepc_backlight_notify(eeepc);
1246 
1247                         /* Convert event to keypress (obsolescent hack) */
1248                         new_brightness = event - NOTIFY_BRN_MIN;
1249 
1250                         if (new_brightness < old_brightness) {
1251                                 event = NOTIFY_BRN_MIN; /* brightness down */
1252                         } else if (new_brightness > old_brightness) {
1253                                 event = NOTIFY_BRN_MAX; /* brightness up */
1254                         } else {
1255                                 /*
1256                                 * no change in brightness - already at min/max,
1257                                 * event will be desired value (or else ignored)
1258                                 */
1259                         }
1260                         eeepc_input_notify(eeepc, event);
1261                 }
1262         } else {
1263                 /* Everything else is a bona-fide keypress event */
1264                 eeepc_input_notify(eeepc, event);
1265         }
1266 }
1267 
1268 static void eeepc_dmi_check(struct eeepc_laptop *eeepc)
1269 {
1270         const char *model;
1271 
1272         model = dmi_get_system_info(DMI_PRODUCT_NAME);
1273         if (!model)
1274                 return;
1275 
1276         /*
1277          * Blacklist for setting cpufv (cpu speed).
1278          *
1279          * EeePC 4G ("701") implements CFVS, but it is not supported
1280          * by the pre-installed OS, and the original option to change it
1281          * in the BIOS setup screen was removed in later versions.
1282          *
1283          * Judging by the lack of "Super Hybrid Engine" on Asus product pages,
1284          * this applies to all "701" models (4G/4G Surf/2G Surf).
1285          *
1286          * So Asus made a deliberate decision not to support it on this model.
1287          * We have several reports that using it can cause the system to hang
1288          *
1289          * The hang has also been reported on a "702" (Model name "8G"?).
1290          *
1291          * We avoid dmi_check_system() / dmi_match(), because they use
1292          * substring matching.  We don't want to affect the "701SD"
1293          * and "701SDX" models, because they do support S.H.E.
1294          */
1295         if (strcmp(model, "701") == 0 || strcmp(model, "702") == 0) {
1296                 eeepc->cpufv_disabled = true;
1297                 pr_info("model %s does not officially support setting cpu "
1298                         "speed\n", model);
1299                 pr_info("cpufv disabled to avoid instability\n");
1300         }
1301 
1302         /*
1303          * Blacklist for wlan hotplug
1304          *
1305          * Eeepc 1005HA doesn't work like others models and don't need the
1306          * hotplug code. In fact, current hotplug code seems to unplug another
1307          * device...
1308          */
1309         if (strcmp(model, "1005HA") == 0 || strcmp(model, "1201N") == 0 ||
1310             strcmp(model, "1005PE") == 0) {
1311                 eeepc->hotplug_disabled = true;
1312                 pr_info("wlan hotplug disabled\n");
1313         }
1314 }
1315 
1316 static void cmsg_quirk(struct eeepc_laptop *eeepc, int cm, const char *name)
1317 {
1318         int dummy;
1319 
1320         /* Some BIOSes do not report cm although it is available.
1321            Check if cm_getv[cm] works and, if yes, assume cm should be set. */
1322         if (!(eeepc->cm_supported & (1 << cm))
1323             && !read_acpi_int(eeepc->handle, cm_getv[cm], &dummy)) {
1324                 pr_info("%s (%x) not reported by BIOS,"
1325                         " enabling anyway\n", name, 1 << cm);
1326                 eeepc->cm_supported |= 1 << cm;
1327         }
1328 }
1329 
1330 static void cmsg_quirks(struct eeepc_laptop *eeepc)
1331 {
1332         cmsg_quirk(eeepc, CM_ASL_LID, "LID");
1333         cmsg_quirk(eeepc, CM_ASL_TYPE, "TYPE");
1334         cmsg_quirk(eeepc, CM_ASL_PANELPOWER, "PANELPOWER");
1335         cmsg_quirk(eeepc, CM_ASL_TPD, "TPD");
1336 }
1337 
1338 static int eeepc_acpi_init(struct eeepc_laptop *eeepc)
1339 {
1340         unsigned int init_flags;
1341         int result;
1342 
1343         result = acpi_bus_get_status(eeepc->device);
1344         if (result)
1345                 return result;
1346         if (!eeepc->device->status.present) {
1347                 pr_err("Hotkey device not present, aborting\n");
1348                 return -ENODEV;
1349         }
1350 
1351         init_flags = DISABLE_ASL_WLAN | DISABLE_ASL_DISPLAYSWITCH;
1352         pr_notice("Hotkey init flags 0x%x\n", init_flags);
1353 
1354         if (write_acpi_int(eeepc->handle, "INIT", init_flags)) {
1355                 pr_err("Hotkey initialization failed\n");
1356                 return -ENODEV;
1357         }
1358 
1359         /* get control methods supported */
1360         if (read_acpi_int(eeepc->handle, "CMSG", &eeepc->cm_supported)) {
1361                 pr_err("Get control methods supported failed\n");
1362                 return -ENODEV;
1363         }
1364         cmsg_quirks(eeepc);
1365         pr_info("Get control methods supported: 0x%x\n", eeepc->cm_supported);
1366 
1367         return 0;
1368 }
1369 
1370 static void eeepc_enable_camera(struct eeepc_laptop *eeepc)
1371 {
1372         /*
1373          * If the following call to set_acpi() fails, it's because there's no
1374          * camera so we can ignore the error.
1375          */
1376         if (get_acpi(eeepc, CM_ASL_CAMERA) == 0)
1377                 set_acpi(eeepc, CM_ASL_CAMERA, 1);
1378 }
1379 
1380 static bool eeepc_device_present;
1381 
1382 static int eeepc_acpi_add(struct acpi_device *device)
1383 {
1384         struct eeepc_laptop *eeepc;
1385         int result;
1386 
1387         pr_notice(EEEPC_LAPTOP_NAME "\n");
1388         eeepc = kzalloc(sizeof(struct eeepc_laptop), GFP_KERNEL);
1389         if (!eeepc)
1390                 return -ENOMEM;
1391         eeepc->handle = device->handle;
1392         strcpy(acpi_device_name(device), EEEPC_ACPI_DEVICE_NAME);
1393         strcpy(acpi_device_class(device), EEEPC_ACPI_CLASS);
1394         device->driver_data = eeepc;
1395         eeepc->device = device;
1396 
1397         eeepc->hotplug_disabled = hotplug_disabled;
1398 
1399         eeepc_dmi_check(eeepc);
1400 
1401         result = eeepc_acpi_init(eeepc);
1402         if (result)
1403                 goto fail_platform;
1404         eeepc_enable_camera(eeepc);
1405 
1406         /*
1407          * Register the platform device first.  It is used as a parent for the
1408          * sub-devices below.
1409          *
1410          * Note that if there are multiple instances of this ACPI device it
1411          * will bail out, because the platform device is registered with a
1412          * fixed name.  Of course it doesn't make sense to have more than one,
1413          * and machine-specific scripts find the fixed name convenient.  But
1414          * It's also good for us to exclude multiple instances because both
1415          * our hwmon and our wlan rfkill subdevice use global ACPI objects
1416          * (the EC and the wlan PCI slot respectively).
1417          */
1418         result = eeepc_platform_init(eeepc);
1419         if (result)
1420                 goto fail_platform;
1421 
1422         if (!acpi_video_backlight_support()) {
1423                 result = eeepc_backlight_init(eeepc);
1424                 if (result)
1425                         goto fail_backlight;
1426         } else {
1427                 pr_info("Backlight controlled by ACPI video driver\n");
1428         }
1429 
1430         result = eeepc_input_init(eeepc);
1431         if (result)
1432                 goto fail_input;
1433 
1434         result = eeepc_hwmon_init(eeepc);
1435         if (result)
1436                 goto fail_hwmon;
1437 
1438         result = eeepc_led_init(eeepc);
1439         if (result)
1440                 goto fail_led;
1441 
1442         result = eeepc_rfkill_init(eeepc);
1443         if (result)
1444                 goto fail_rfkill;
1445 
1446         eeepc_device_present = true;
1447         return 0;
1448 
1449 fail_rfkill:
1450         eeepc_led_exit(eeepc);
1451 fail_led:
1452 fail_hwmon:
1453         eeepc_input_exit(eeepc);
1454 fail_input:
1455         eeepc_backlight_exit(eeepc);
1456 fail_backlight:
1457         eeepc_platform_exit(eeepc);
1458 fail_platform:
1459         kfree(eeepc);
1460 
1461         return result;
1462 }
1463 
1464 static int eeepc_acpi_remove(struct acpi_device *device)
1465 {
1466         struct eeepc_laptop *eeepc = acpi_driver_data(device);
1467 
1468         eeepc_backlight_exit(eeepc);
1469         eeepc_rfkill_exit(eeepc);
1470         eeepc_input_exit(eeepc);
1471         eeepc_led_exit(eeepc);
1472         eeepc_platform_exit(eeepc);
1473 
1474         kfree(eeepc);
1475         return 0;
1476 }
1477 
1478 
1479 static const struct acpi_device_id eeepc_device_ids[] = {
1480         {EEEPC_ACPI_HID, 0},
1481         {"", 0},
1482 };
1483 MODULE_DEVICE_TABLE(acpi, eeepc_device_ids);
1484 
1485 static struct acpi_driver eeepc_acpi_driver = {
1486         .name = EEEPC_LAPTOP_NAME,
1487         .class = EEEPC_ACPI_CLASS,
1488         .owner = THIS_MODULE,
1489         .ids = eeepc_device_ids,
1490         .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
1491         .ops = {
1492                 .add = eeepc_acpi_add,
1493                 .remove = eeepc_acpi_remove,
1494                 .notify = eeepc_acpi_notify,
1495         },
1496 };
1497 
1498 
1499 static int __init eeepc_laptop_init(void)
1500 {
1501         int result;
1502 
1503         result = platform_driver_register(&platform_driver);
1504         if (result < 0)
1505                 return result;
1506 
1507         result = acpi_bus_register_driver(&eeepc_acpi_driver);
1508         if (result < 0)
1509                 goto fail_acpi_driver;
1510 
1511         if (!eeepc_device_present) {
1512                 result = -ENODEV;
1513                 goto fail_no_device;
1514         }
1515 
1516         return 0;
1517 
1518 fail_no_device:
1519         acpi_bus_unregister_driver(&eeepc_acpi_driver);
1520 fail_acpi_driver:
1521         platform_driver_unregister(&platform_driver);
1522         return result;
1523 }
1524 
1525 static void __exit eeepc_laptop_exit(void)
1526 {
1527         acpi_bus_unregister_driver(&eeepc_acpi_driver);
1528         platform_driver_unregister(&platform_driver);
1529 }
1530 
1531 module_init(eeepc_laptop_init);
1532 module_exit(eeepc_laptop_exit);
1533 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us