Version:  2.0.40 2.2.26 2.4.37 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 3.19 4.0 4.1

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 on this model)\n");
421                 eeepc->cpufv_disabled = false;
422                 return count;
423         case 1:
424                 return -EPERM;
425         default:
426                 return -EINVAL;
427         }
428 }
429 
430 
431 static DEVICE_ATTR_RW(cpufv);
432 static DEVICE_ATTR_RO(available_cpufv);
433 static DEVICE_ATTR_RW(cpufv_disabled);
434 
435 static struct attribute *platform_attributes[] = {
436         &dev_attr_camera.attr,
437         &dev_attr_cardr.attr,
438         &dev_attr_disp.attr,
439         &dev_attr_cpufv.attr,
440         &dev_attr_available_cpufv.attr,
441         &dev_attr_cpufv_disabled.attr,
442         NULL
443 };
444 
445 static struct attribute_group platform_attribute_group = {
446         .attrs = platform_attributes
447 };
448 
449 static int eeepc_platform_init(struct eeepc_laptop *eeepc)
450 {
451         int result;
452 
453         eeepc->platform_device = platform_device_alloc(EEEPC_LAPTOP_FILE, -1);
454         if (!eeepc->platform_device)
455                 return -ENOMEM;
456         platform_set_drvdata(eeepc->platform_device, eeepc);
457 
458         result = platform_device_add(eeepc->platform_device);
459         if (result)
460                 goto fail_platform_device;
461 
462         result = sysfs_create_group(&eeepc->platform_device->dev.kobj,
463                                     &platform_attribute_group);
464         if (result)
465                 goto fail_sysfs;
466         return 0;
467 
468 fail_sysfs:
469         platform_device_del(eeepc->platform_device);
470 fail_platform_device:
471         platform_device_put(eeepc->platform_device);
472         return result;
473 }
474 
475 static void eeepc_platform_exit(struct eeepc_laptop *eeepc)
476 {
477         sysfs_remove_group(&eeepc->platform_device->dev.kobj,
478                            &platform_attribute_group);
479         platform_device_unregister(eeepc->platform_device);
480 }
481 
482 /*
483  * LEDs
484  */
485 /*
486  * These functions actually update the LED's, and are called from a
487  * workqueue. By doing this as separate work rather than when the LED
488  * subsystem asks, we avoid messing with the Asus ACPI stuff during a
489  * potentially bad time, such as a timer interrupt.
490  */
491 static void tpd_led_update(struct work_struct *work)
492  {
493         struct eeepc_laptop *eeepc;
494 
495         eeepc = container_of(work, struct eeepc_laptop, tpd_led_work);
496 
497         set_acpi(eeepc, CM_ASL_TPD, eeepc->tpd_led_wk);
498 }
499 
500 static void tpd_led_set(struct led_classdev *led_cdev,
501                         enum led_brightness value)
502 {
503         struct eeepc_laptop *eeepc;
504 
505         eeepc = container_of(led_cdev, struct eeepc_laptop, tpd_led);
506 
507         eeepc->tpd_led_wk = (value > 0) ? 1 : 0;
508         queue_work(eeepc->led_workqueue, &eeepc->tpd_led_work);
509 }
510 
511 static enum led_brightness tpd_led_get(struct led_classdev *led_cdev)
512 {
513         struct eeepc_laptop *eeepc;
514 
515         eeepc = container_of(led_cdev, struct eeepc_laptop, tpd_led);
516 
517         return get_acpi(eeepc, CM_ASL_TPD);
518 }
519 
520 static int eeepc_led_init(struct eeepc_laptop *eeepc)
521 {
522         int rv;
523 
524         if (get_acpi(eeepc, CM_ASL_TPD) == -ENODEV)
525                 return 0;
526 
527         eeepc->led_workqueue = create_singlethread_workqueue("led_workqueue");
528         if (!eeepc->led_workqueue)
529                 return -ENOMEM;
530         INIT_WORK(&eeepc->tpd_led_work, tpd_led_update);
531 
532         eeepc->tpd_led.name = "eeepc::touchpad";
533         eeepc->tpd_led.brightness_set = tpd_led_set;
534         if (get_acpi(eeepc, CM_ASL_TPD) >= 0) /* if method is available */
535                 eeepc->tpd_led.brightness_get = tpd_led_get;
536         eeepc->tpd_led.max_brightness = 1;
537 
538         rv = led_classdev_register(&eeepc->platform_device->dev,
539                                    &eeepc->tpd_led);
540         if (rv) {
541                 destroy_workqueue(eeepc->led_workqueue);
542                 return rv;
543         }
544 
545         return 0;
546 }
547 
548 static void eeepc_led_exit(struct eeepc_laptop *eeepc)
549 {
550         if (!IS_ERR_OR_NULL(eeepc->tpd_led.dev))
551                 led_classdev_unregister(&eeepc->tpd_led);
552         if (eeepc->led_workqueue)
553                 destroy_workqueue(eeepc->led_workqueue);
554 }
555 
556 
557 /*
558  * PCI hotplug (for wlan rfkill)
559  */
560 static bool eeepc_wlan_rfkill_blocked(struct eeepc_laptop *eeepc)
561 {
562         if (get_acpi(eeepc, CM_ASL_WLAN) == 1)
563                 return false;
564         return true;
565 }
566 
567 static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc, acpi_handle handle)
568 {
569         struct pci_dev *port;
570         struct pci_dev *dev;
571         struct pci_bus *bus;
572         bool blocked = eeepc_wlan_rfkill_blocked(eeepc);
573         bool absent;
574         u32 l;
575 
576         if (eeepc->wlan_rfkill)
577                 rfkill_set_sw_state(eeepc->wlan_rfkill, blocked);
578 
579         mutex_lock(&eeepc->hotplug_lock);
580         pci_lock_rescan_remove();
581 
582         if (!eeepc->hotplug_slot)
583                 goto out_unlock;
584 
585         port = acpi_get_pci_dev(handle);
586         if (!port) {
587                 pr_warning("Unable to find port\n");
588                 goto out_unlock;
589         }
590 
591         bus = port->subordinate;
592 
593         if (!bus) {
594                 pr_warn("Unable to find PCI bus 1?\n");
595                 goto out_put_dev;
596         }
597 
598         if (pci_bus_read_config_dword(bus, 0, PCI_VENDOR_ID, &l)) {
599                 pr_err("Unable to read PCI config space?\n");
600                 goto out_put_dev;
601         }
602 
603         absent = (l == 0xffffffff);
604 
605         if (blocked != absent) {
606                 pr_warn("BIOS says wireless lan is %s, but the pci device is %s\n",
607                         blocked ? "blocked" : "unblocked",
608                         absent ? "absent" : "present");
609                 pr_warn("skipped wireless hotplug as probably inappropriate for this model\n");
610                 goto out_put_dev;
611         }
612 
613         if (!blocked) {
614                 dev = pci_get_slot(bus, 0);
615                 if (dev) {
616                         /* Device already present */
617                         pci_dev_put(dev);
618                         goto out_put_dev;
619                 }
620                 dev = pci_scan_single_device(bus, 0);
621                 if (dev) {
622                         pci_bus_assign_resources(bus);
623                         pci_bus_add_device(dev);
624                 }
625         } else {
626                 dev = pci_get_slot(bus, 0);
627                 if (dev) {
628                         pci_stop_and_remove_bus_device(dev);
629                         pci_dev_put(dev);
630                 }
631         }
632 out_put_dev:
633         pci_dev_put(port);
634 
635 out_unlock:
636         pci_unlock_rescan_remove();
637         mutex_unlock(&eeepc->hotplug_lock);
638 }
639 
640 static void eeepc_rfkill_hotplug_update(struct eeepc_laptop *eeepc, char *node)
641 {
642         acpi_status status = AE_OK;
643         acpi_handle handle;
644 
645         status = acpi_get_handle(NULL, node, &handle);
646 
647         if (ACPI_SUCCESS(status))
648                 eeepc_rfkill_hotplug(eeepc, handle);
649 }
650 
651 static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
652 {
653         struct eeepc_laptop *eeepc = data;
654 
655         if (event != ACPI_NOTIFY_BUS_CHECK)
656                 return;
657 
658         eeepc_rfkill_hotplug(eeepc, handle);
659 }
660 
661 static int eeepc_register_rfkill_notifier(struct eeepc_laptop *eeepc,
662                                           char *node)
663 {
664         acpi_status status;
665         acpi_handle handle;
666 
667         status = acpi_get_handle(NULL, node, &handle);
668 
669         if (ACPI_FAILURE(status))
670                 return -ENODEV;
671 
672         status = acpi_install_notify_handler(handle,
673                                              ACPI_SYSTEM_NOTIFY,
674                                              eeepc_rfkill_notify,
675                                              eeepc);
676         if (ACPI_FAILURE(status))
677                 pr_warn("Failed to register notify on %s\n", node);
678 
679         /*
680          * Refresh pci hotplug in case the rfkill state was
681          * changed during setup.
682          */
683         eeepc_rfkill_hotplug(eeepc, handle);
684         return 0;
685 }
686 
687 static void eeepc_unregister_rfkill_notifier(struct eeepc_laptop *eeepc,
688                                              char *node)
689 {
690         acpi_status status = AE_OK;
691         acpi_handle handle;
692 
693         status = acpi_get_handle(NULL, node, &handle);
694 
695         if (ACPI_FAILURE(status))
696                 return;
697 
698         status = acpi_remove_notify_handler(handle,
699                                              ACPI_SYSTEM_NOTIFY,
700                                              eeepc_rfkill_notify);
701         if (ACPI_FAILURE(status))
702                 pr_err("Error removing rfkill notify handler %s\n",
703                         node);
704                 /*
705                  * Refresh pci hotplug in case the rfkill
706                  * state was changed after
707                  * eeepc_unregister_rfkill_notifier()
708                  */
709         eeepc_rfkill_hotplug(eeepc, handle);
710 }
711 
712 static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot,
713                                     u8 *value)
714 {
715         struct eeepc_laptop *eeepc = hotplug_slot->private;
716         int val = get_acpi(eeepc, CM_ASL_WLAN);
717 
718         if (val == 1 || val == 0)
719                 *value = val;
720         else
721                 return -EINVAL;
722 
723         return 0;
724 }
725 
726 static void eeepc_cleanup_pci_hotplug(struct hotplug_slot *hotplug_slot)
727 {
728         kfree(hotplug_slot->info);
729         kfree(hotplug_slot);
730 }
731 
732 static struct hotplug_slot_ops eeepc_hotplug_slot_ops = {
733         .owner = THIS_MODULE,
734         .get_adapter_status = eeepc_get_adapter_status,
735         .get_power_status = eeepc_get_adapter_status,
736 };
737 
738 static int eeepc_setup_pci_hotplug(struct eeepc_laptop *eeepc)
739 {
740         int ret = -ENOMEM;
741         struct pci_bus *bus = pci_find_bus(0, 1);
742 
743         if (!bus) {
744                 pr_err("Unable to find wifi PCI bus\n");
745                 return -ENODEV;
746         }
747 
748         eeepc->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
749         if (!eeepc->hotplug_slot)
750                 goto error_slot;
751 
752         eeepc->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info),
753                                             GFP_KERNEL);
754         if (!eeepc->hotplug_slot->info)
755                 goto error_info;
756 
757         eeepc->hotplug_slot->private = eeepc;
758         eeepc->hotplug_slot->release = &eeepc_cleanup_pci_hotplug;
759         eeepc->hotplug_slot->ops = &eeepc_hotplug_slot_ops;
760         eeepc_get_adapter_status(eeepc->hotplug_slot,
761                                  &eeepc->hotplug_slot->info->adapter_status);
762 
763         ret = pci_hp_register(eeepc->hotplug_slot, bus, 0, "eeepc-wifi");
764         if (ret) {
765                 pr_err("Unable to register hotplug slot - %d\n", ret);
766                 goto error_register;
767         }
768 
769         return 0;
770 
771 error_register:
772         kfree(eeepc->hotplug_slot->info);
773 error_info:
774         kfree(eeepc->hotplug_slot);
775         eeepc->hotplug_slot = NULL;
776 error_slot:
777         return ret;
778 }
779 
780 /*
781  * Rfkill devices
782  */
783 static int eeepc_rfkill_set(void *data, bool blocked)
784 {
785         acpi_handle handle = data;
786 
787         return write_acpi_int(handle, NULL, !blocked);
788 }
789 
790 static const struct rfkill_ops eeepc_rfkill_ops = {
791         .set_block = eeepc_rfkill_set,
792 };
793 
794 static int eeepc_new_rfkill(struct eeepc_laptop *eeepc,
795                             struct rfkill **rfkill,
796                             const char *name,
797                             enum rfkill_type type, int cm)
798 {
799         acpi_handle handle;
800         int result;
801 
802         result = acpi_setter_handle(eeepc, cm, &handle);
803         if (result < 0)
804                 return result;
805 
806         *rfkill = rfkill_alloc(name, &eeepc->platform_device->dev, type,
807                                &eeepc_rfkill_ops, handle);
808 
809         if (!*rfkill)
810                 return -EINVAL;
811 
812         rfkill_init_sw_state(*rfkill, get_acpi(eeepc, cm) != 1);
813         result = rfkill_register(*rfkill);
814         if (result) {
815                 rfkill_destroy(*rfkill);
816                 *rfkill = NULL;
817                 return result;
818         }
819         return 0;
820 }
821 
822 static char EEEPC_RFKILL_NODE_1[] = "\\_SB.PCI0.P0P5";
823 static char EEEPC_RFKILL_NODE_2[] = "\\_SB.PCI0.P0P6";
824 static char EEEPC_RFKILL_NODE_3[] = "\\_SB.PCI0.P0P7";
825 
826 static void eeepc_rfkill_exit(struct eeepc_laptop *eeepc)
827 {
828         eeepc_unregister_rfkill_notifier(eeepc, EEEPC_RFKILL_NODE_1);
829         eeepc_unregister_rfkill_notifier(eeepc, EEEPC_RFKILL_NODE_2);
830         eeepc_unregister_rfkill_notifier(eeepc, EEEPC_RFKILL_NODE_3);
831         if (eeepc->wlan_rfkill) {
832                 rfkill_unregister(eeepc->wlan_rfkill);
833                 rfkill_destroy(eeepc->wlan_rfkill);
834                 eeepc->wlan_rfkill = NULL;
835         }
836 
837         if (eeepc->hotplug_slot)
838                 pci_hp_deregister(eeepc->hotplug_slot);
839 
840         if (eeepc->bluetooth_rfkill) {
841                 rfkill_unregister(eeepc->bluetooth_rfkill);
842                 rfkill_destroy(eeepc->bluetooth_rfkill);
843                 eeepc->bluetooth_rfkill = NULL;
844         }
845         if (eeepc->wwan3g_rfkill) {
846                 rfkill_unregister(eeepc->wwan3g_rfkill);
847                 rfkill_destroy(eeepc->wwan3g_rfkill);
848                 eeepc->wwan3g_rfkill = NULL;
849         }
850         if (eeepc->wimax_rfkill) {
851                 rfkill_unregister(eeepc->wimax_rfkill);
852                 rfkill_destroy(eeepc->wimax_rfkill);
853                 eeepc->wimax_rfkill = NULL;
854         }
855 }
856 
857 static int eeepc_rfkill_init(struct eeepc_laptop *eeepc)
858 {
859         int result = 0;
860 
861         mutex_init(&eeepc->hotplug_lock);
862 
863         result = eeepc_new_rfkill(eeepc, &eeepc->wlan_rfkill,
864                                   "eeepc-wlan", RFKILL_TYPE_WLAN,
865                                   CM_ASL_WLAN);
866 
867         if (result && result != -ENODEV)
868                 goto exit;
869 
870         result = eeepc_new_rfkill(eeepc, &eeepc->bluetooth_rfkill,
871                                   "eeepc-bluetooth", RFKILL_TYPE_BLUETOOTH,
872                                   CM_ASL_BLUETOOTH);
873 
874         if (result && result != -ENODEV)
875                 goto exit;
876 
877         result = eeepc_new_rfkill(eeepc, &eeepc->wwan3g_rfkill,
878                                   "eeepc-wwan3g", RFKILL_TYPE_WWAN,
879                                   CM_ASL_3G);
880 
881         if (result && result != -ENODEV)
882                 goto exit;
883 
884         result = eeepc_new_rfkill(eeepc, &eeepc->wimax_rfkill,
885                                   "eeepc-wimax", RFKILL_TYPE_WIMAX,
886                                   CM_ASL_WIMAX);
887 
888         if (result && result != -ENODEV)
889                 goto exit;
890 
891         if (eeepc->hotplug_disabled)
892                 return 0;
893 
894         result = eeepc_setup_pci_hotplug(eeepc);
895         /*
896          * If we get -EBUSY then something else is handling the PCI hotplug -
897          * don't fail in this case
898          */
899         if (result == -EBUSY)
900                 result = 0;
901 
902         eeepc_register_rfkill_notifier(eeepc, EEEPC_RFKILL_NODE_1);
903         eeepc_register_rfkill_notifier(eeepc, EEEPC_RFKILL_NODE_2);
904         eeepc_register_rfkill_notifier(eeepc, EEEPC_RFKILL_NODE_3);
905 
906 exit:
907         if (result && result != -ENODEV)
908                 eeepc_rfkill_exit(eeepc);
909         return result;
910 }
911 
912 /*
913  * Platform driver - hibernate/resume callbacks
914  */
915 static int eeepc_hotk_thaw(struct device *device)
916 {
917         struct eeepc_laptop *eeepc = dev_get_drvdata(device);
918 
919         if (eeepc->wlan_rfkill) {
920                 int wlan;
921 
922                 /*
923                  * Work around bios bug - acpi _PTS turns off the wireless led
924                  * during suspend.  Normally it restores it on resume, but
925                  * we should kick it ourselves in case hibernation is aborted.
926                  */
927                 wlan = get_acpi(eeepc, CM_ASL_WLAN);
928                 if (wlan >= 0)
929                         set_acpi(eeepc, CM_ASL_WLAN, wlan);
930         }
931 
932         return 0;
933 }
934 
935 static int eeepc_hotk_restore(struct device *device)
936 {
937         struct eeepc_laptop *eeepc = dev_get_drvdata(device);
938 
939         /* Refresh both wlan rfkill state and pci hotplug */
940         if (eeepc->wlan_rfkill) {
941                 eeepc_rfkill_hotplug_update(eeepc, EEEPC_RFKILL_NODE_1);
942                 eeepc_rfkill_hotplug_update(eeepc, EEEPC_RFKILL_NODE_2);
943                 eeepc_rfkill_hotplug_update(eeepc, EEEPC_RFKILL_NODE_3);
944         }
945 
946         if (eeepc->bluetooth_rfkill)
947                 rfkill_set_sw_state(eeepc->bluetooth_rfkill,
948                                     get_acpi(eeepc, CM_ASL_BLUETOOTH) != 1);
949         if (eeepc->wwan3g_rfkill)
950                 rfkill_set_sw_state(eeepc->wwan3g_rfkill,
951                                     get_acpi(eeepc, CM_ASL_3G) != 1);
952         if (eeepc->wimax_rfkill)
953                 rfkill_set_sw_state(eeepc->wimax_rfkill,
954                                     get_acpi(eeepc, CM_ASL_WIMAX) != 1);
955 
956         return 0;
957 }
958 
959 static const struct dev_pm_ops eeepc_pm_ops = {
960         .thaw = eeepc_hotk_thaw,
961         .restore = eeepc_hotk_restore,
962 };
963 
964 static struct platform_driver platform_driver = {
965         .driver = {
966                 .name = EEEPC_LAPTOP_FILE,
967                 .pm = &eeepc_pm_ops,
968         }
969 };
970 
971 /*
972  * Hwmon device
973  */
974 
975 #define EEEPC_EC_SC00      0x61
976 #define EEEPC_EC_FAN_PWM   (EEEPC_EC_SC00 + 2) /* Fan PWM duty cycle (%) */
977 #define EEEPC_EC_FAN_HRPM  (EEEPC_EC_SC00 + 5) /* High byte, fan speed (RPM) */
978 #define EEEPC_EC_FAN_LRPM  (EEEPC_EC_SC00 + 6) /* Low byte, fan speed (RPM) */
979 
980 #define EEEPC_EC_SFB0      0xD0
981 #define EEEPC_EC_FAN_CTRL  (EEEPC_EC_SFB0 + 3) /* Byte containing SF25  */
982 
983 static inline int eeepc_pwm_to_lmsensors(int value)
984 {
985         return value * 255 / 100;
986 }
987 
988 static inline int eeepc_lmsensors_to_pwm(int value)
989 {
990         value = clamp_val(value, 0, 255);
991         return value * 100 / 255;
992 }
993 
994 static int eeepc_get_fan_pwm(void)
995 {
996         u8 value = 0;
997 
998         ec_read(EEEPC_EC_FAN_PWM, &value);
999         return eeepc_pwm_to_lmsensors(value);
1000 }
1001 
1002 static void eeepc_set_fan_pwm(int value)
1003 {
1004         value = eeepc_lmsensors_to_pwm(value);
1005         ec_write(EEEPC_EC_FAN_PWM, value);
1006 }
1007 
1008 static int eeepc_get_fan_rpm(void)
1009 {
1010         u8 high = 0;
1011         u8 low = 0;
1012 
1013         ec_read(EEEPC_EC_FAN_HRPM, &high);
1014         ec_read(EEEPC_EC_FAN_LRPM, &low);
1015         return high << 8 | low;
1016 }
1017 
1018 #define EEEPC_EC_FAN_CTRL_BIT   0x02
1019 #define EEEPC_FAN_CTRL_MANUAL   1
1020 #define EEEPC_FAN_CTRL_AUTO     2
1021 
1022 static int eeepc_get_fan_ctrl(void)
1023 {
1024         u8 value = 0;
1025 
1026         ec_read(EEEPC_EC_FAN_CTRL, &value);
1027         if (value & EEEPC_EC_FAN_CTRL_BIT)
1028                 return EEEPC_FAN_CTRL_MANUAL;
1029         else
1030                 return EEEPC_FAN_CTRL_AUTO;
1031 }
1032 
1033 static void eeepc_set_fan_ctrl(int manual)
1034 {
1035         u8 value = 0;
1036 
1037         ec_read(EEEPC_EC_FAN_CTRL, &value);
1038         if (manual == EEEPC_FAN_CTRL_MANUAL)
1039                 value |= EEEPC_EC_FAN_CTRL_BIT;
1040         else
1041                 value &= ~EEEPC_EC_FAN_CTRL_BIT;
1042         ec_write(EEEPC_EC_FAN_CTRL, value);
1043 }
1044 
1045 static ssize_t store_sys_hwmon(void (*set)(int), const char *buf, size_t count)
1046 {
1047         int rv, value;
1048 
1049         rv = parse_arg(buf, &value);
1050         if (rv < 0)
1051                 return rv;
1052         set(value);
1053         return count;
1054 }
1055 
1056 static ssize_t show_sys_hwmon(int (*get)(void), char *buf)
1057 {
1058         return sprintf(buf, "%d\n", get());
1059 }
1060 
1061 #define EEEPC_SENSOR_SHOW_FUNC(_name, _get)                             \
1062         static ssize_t _name##_show(struct device *dev,                 \
1063                                     struct device_attribute *attr,      \
1064                                     char *buf)                          \
1065         {                                                               \
1066                 return show_sys_hwmon(_get, buf);                       \
1067         }
1068 
1069 #define EEEPC_SENSOR_STORE_FUNC(_name, _set)                            \
1070         static ssize_t _name##_store(struct device *dev,                \
1071                                      struct device_attribute *attr,     \
1072                                      const char *buf, size_t count)     \
1073         {                                                               \
1074                 return store_sys_hwmon(_set, buf, count);               \
1075         }
1076 
1077 #define EEEPC_CREATE_SENSOR_ATTR_RW(_name, _get, _set)                  \
1078         EEEPC_SENSOR_SHOW_FUNC(_name, _get)                             \
1079         EEEPC_SENSOR_STORE_FUNC(_name, _set)                            \
1080         static DEVICE_ATTR_RW(_name)
1081 
1082 #define EEEPC_CREATE_SENSOR_ATTR_RO(_name, _get)                        \
1083         EEEPC_SENSOR_SHOW_FUNC(_name, _get)                             \
1084         static DEVICE_ATTR_RO(_name)
1085 
1086 EEEPC_CREATE_SENSOR_ATTR_RO(fan1_input, eeepc_get_fan_rpm);
1087 EEEPC_CREATE_SENSOR_ATTR_RW(pwm1, eeepc_get_fan_pwm,
1088                             eeepc_set_fan_pwm);
1089 EEEPC_CREATE_SENSOR_ATTR_RW(pwm1_enable, eeepc_get_fan_ctrl,
1090                             eeepc_set_fan_ctrl);
1091 
1092 static struct attribute *hwmon_attrs[] = {
1093         &dev_attr_pwm1.attr,
1094         &dev_attr_fan1_input.attr,
1095         &dev_attr_pwm1_enable.attr,
1096         NULL
1097 };
1098 ATTRIBUTE_GROUPS(hwmon);
1099 
1100 static int eeepc_hwmon_init(struct eeepc_laptop *eeepc)
1101 {
1102         struct device *dev = &eeepc->platform_device->dev;
1103         struct device *hwmon;
1104 
1105         hwmon = devm_hwmon_device_register_with_groups(dev, "eeepc", NULL,
1106                                                        hwmon_groups);
1107         if (IS_ERR(hwmon)) {
1108                 pr_err("Could not register eeepc hwmon device\n");
1109                 return PTR_ERR(hwmon);
1110         }
1111         return 0;
1112 }
1113 
1114 /*
1115  * Backlight device
1116  */
1117 static int read_brightness(struct backlight_device *bd)
1118 {
1119         struct eeepc_laptop *eeepc = bl_get_data(bd);
1120 
1121         return get_acpi(eeepc, CM_ASL_PANELBRIGHT);
1122 }
1123 
1124 static int set_brightness(struct backlight_device *bd, int value)
1125 {
1126         struct eeepc_laptop *eeepc = bl_get_data(bd);
1127 
1128         return set_acpi(eeepc, CM_ASL_PANELBRIGHT, value);
1129 }
1130 
1131 static int update_bl_status(struct backlight_device *bd)
1132 {
1133         return set_brightness(bd, bd->props.brightness);
1134 }
1135 
1136 static const struct backlight_ops eeepcbl_ops = {
1137         .get_brightness = read_brightness,
1138         .update_status = update_bl_status,
1139 };
1140 
1141 static int eeepc_backlight_notify(struct eeepc_laptop *eeepc)
1142 {
1143         struct backlight_device *bd = eeepc->backlight_device;
1144         int old = bd->props.brightness;
1145 
1146         backlight_force_update(bd, BACKLIGHT_UPDATE_HOTKEY);
1147 
1148         return old;
1149 }
1150 
1151 static int eeepc_backlight_init(struct eeepc_laptop *eeepc)
1152 {
1153         struct backlight_properties props;
1154         struct backlight_device *bd;
1155 
1156         memset(&props, 0, sizeof(struct backlight_properties));
1157         props.type = BACKLIGHT_PLATFORM;
1158         props.max_brightness = 15;
1159         bd = backlight_device_register(EEEPC_LAPTOP_FILE,
1160                                        &eeepc->platform_device->dev, eeepc,
1161                                        &eeepcbl_ops, &props);
1162         if (IS_ERR(bd)) {
1163                 pr_err("Could not register eeepc backlight device\n");
1164                 eeepc->backlight_device = NULL;
1165                 return PTR_ERR(bd);
1166         }
1167         eeepc->backlight_device = bd;
1168         bd->props.brightness = read_brightness(bd);
1169         bd->props.power = FB_BLANK_UNBLANK;
1170         backlight_update_status(bd);
1171         return 0;
1172 }
1173 
1174 static void eeepc_backlight_exit(struct eeepc_laptop *eeepc)
1175 {
1176         backlight_device_unregister(eeepc->backlight_device);
1177         eeepc->backlight_device = NULL;
1178 }
1179 
1180 
1181 /*
1182  * Input device (i.e. hotkeys)
1183  */
1184 static int eeepc_input_init(struct eeepc_laptop *eeepc)
1185 {
1186         struct input_dev *input;
1187         int error;
1188 
1189         input = input_allocate_device();
1190         if (!input)
1191                 return -ENOMEM;
1192 
1193         input->name = "Asus EeePC extra buttons";
1194         input->phys = EEEPC_LAPTOP_FILE "/input0";
1195         input->id.bustype = BUS_HOST;
1196         input->dev.parent = &eeepc->platform_device->dev;
1197 
1198         error = sparse_keymap_setup(input, eeepc_keymap, NULL);
1199         if (error) {
1200                 pr_err("Unable to setup input device keymap\n");
1201                 goto err_free_dev;
1202         }
1203 
1204         error = input_register_device(input);
1205         if (error) {
1206                 pr_err("Unable to register input device\n");
1207                 goto err_free_keymap;
1208         }
1209 
1210         eeepc->inputdev = input;
1211         return 0;
1212 
1213 err_free_keymap:
1214         sparse_keymap_free(input);
1215 err_free_dev:
1216         input_free_device(input);
1217         return error;
1218 }
1219 
1220 static void eeepc_input_exit(struct eeepc_laptop *eeepc)
1221 {
1222         if (eeepc->inputdev) {
1223                 sparse_keymap_free(eeepc->inputdev);
1224                 input_unregister_device(eeepc->inputdev);
1225         }
1226         eeepc->inputdev = NULL;
1227 }
1228 
1229 /*
1230  * ACPI driver
1231  */
1232 static void eeepc_input_notify(struct eeepc_laptop *eeepc, int event)
1233 {
1234         if (!eeepc->inputdev)
1235                 return;
1236         if (!sparse_keymap_report_event(eeepc->inputdev, event, 1, true))
1237                 pr_info("Unknown key %x pressed\n", event);
1238 }
1239 
1240 static void eeepc_acpi_notify(struct acpi_device *device, u32 event)
1241 {
1242         struct eeepc_laptop *eeepc = acpi_driver_data(device);
1243         int old_brightness, new_brightness;
1244         u16 count;
1245 
1246         if (event > ACPI_MAX_SYS_NOTIFY)
1247                 return;
1248         count = eeepc->event_count[event % 128]++;
1249         acpi_bus_generate_netlink_event(device->pnp.device_class,
1250                                         dev_name(&device->dev), event,
1251                                         count);
1252 
1253         /* Brightness events are special */
1254         if (event < NOTIFY_BRN_MIN || event > NOTIFY_BRN_MAX) {
1255                 eeepc_input_notify(eeepc, event);
1256                 return;
1257         }
1258 
1259         /* Ignore them completely if the acpi video driver is used */
1260         if (!eeepc->backlight_device)
1261                 return;
1262 
1263         /* Update the backlight device. */
1264         old_brightness = eeepc_backlight_notify(eeepc);
1265 
1266         /* Convert event to keypress (obsolescent hack) */
1267         new_brightness = event - NOTIFY_BRN_MIN;
1268 
1269         if (new_brightness < old_brightness) {
1270                 event = NOTIFY_BRN_MIN; /* brightness down */
1271         } else if (new_brightness > old_brightness) {
1272                 event = NOTIFY_BRN_MAX; /* brightness up */
1273         } else {
1274                 /*
1275                  * no change in brightness - already at min/max,
1276                  * event will be desired value (or else ignored)
1277                  */
1278         }
1279         eeepc_input_notify(eeepc, event);
1280 }
1281 
1282 static void eeepc_dmi_check(struct eeepc_laptop *eeepc)
1283 {
1284         const char *model;
1285 
1286         model = dmi_get_system_info(DMI_PRODUCT_NAME);
1287         if (!model)
1288                 return;
1289 
1290         /*
1291          * Blacklist for setting cpufv (cpu speed).
1292          *
1293          * EeePC 4G ("701") implements CFVS, but it is not supported
1294          * by the pre-installed OS, and the original option to change it
1295          * in the BIOS setup screen was removed in later versions.
1296          *
1297          * Judging by the lack of "Super Hybrid Engine" on Asus product pages,
1298          * this applies to all "701" models (4G/4G Surf/2G Surf).
1299          *
1300          * So Asus made a deliberate decision not to support it on this model.
1301          * We have several reports that using it can cause the system to hang
1302          *
1303          * The hang has also been reported on a "702" (Model name "8G"?).
1304          *
1305          * We avoid dmi_check_system() / dmi_match(), because they use
1306          * substring matching.  We don't want to affect the "701SD"
1307          * and "701SDX" models, because they do support S.H.E.
1308          */
1309         if (strcmp(model, "701") == 0 || strcmp(model, "702") == 0) {
1310                 eeepc->cpufv_disabled = true;
1311                 pr_info("model %s does not officially support setting cpu speed\n",
1312                         model);
1313                 pr_info("cpufv disabled to avoid instability\n");
1314         }
1315 
1316         /*
1317          * Blacklist for wlan hotplug
1318          *
1319          * Eeepc 1005HA doesn't work like others models and don't need the
1320          * hotplug code. In fact, current hotplug code seems to unplug another
1321          * device...
1322          */
1323         if (strcmp(model, "1005HA") == 0 || strcmp(model, "1201N") == 0 ||
1324             strcmp(model, "1005PE") == 0) {
1325                 eeepc->hotplug_disabled = true;
1326                 pr_info("wlan hotplug disabled\n");
1327         }
1328 }
1329 
1330 static void cmsg_quirk(struct eeepc_laptop *eeepc, int cm, const char *name)
1331 {
1332         int dummy;
1333 
1334         /* Some BIOSes do not report cm although it is available.
1335            Check if cm_getv[cm] works and, if yes, assume cm should be set. */
1336         if (!(eeepc->cm_supported & (1 << cm))
1337             && !read_acpi_int(eeepc->handle, cm_getv[cm], &dummy)) {
1338                 pr_info("%s (%x) not reported by BIOS, enabling anyway\n",
1339                         name, 1 << cm);
1340                 eeepc->cm_supported |= 1 << cm;
1341         }
1342 }
1343 
1344 static void cmsg_quirks(struct eeepc_laptop *eeepc)
1345 {
1346         cmsg_quirk(eeepc, CM_ASL_LID, "LID");
1347         cmsg_quirk(eeepc, CM_ASL_TYPE, "TYPE");
1348         cmsg_quirk(eeepc, CM_ASL_PANELPOWER, "PANELPOWER");
1349         cmsg_quirk(eeepc, CM_ASL_TPD, "TPD");
1350 }
1351 
1352 static int eeepc_acpi_init(struct eeepc_laptop *eeepc)
1353 {
1354         unsigned int init_flags;
1355         int result;
1356 
1357         result = acpi_bus_get_status(eeepc->device);
1358         if (result)
1359                 return result;
1360         if (!eeepc->device->status.present) {
1361                 pr_err("Hotkey device not present, aborting\n");
1362                 return -ENODEV;
1363         }
1364 
1365         init_flags = DISABLE_ASL_WLAN | DISABLE_ASL_DISPLAYSWITCH;
1366         pr_notice("Hotkey init flags 0x%x\n", init_flags);
1367 
1368         if (write_acpi_int(eeepc->handle, "INIT", init_flags)) {
1369                 pr_err("Hotkey initialization failed\n");
1370                 return -ENODEV;
1371         }
1372 
1373         /* get control methods supported */
1374         if (read_acpi_int(eeepc->handle, "CMSG", &eeepc->cm_supported)) {
1375                 pr_err("Get control methods supported failed\n");
1376                 return -ENODEV;
1377         }
1378         cmsg_quirks(eeepc);
1379         pr_info("Get control methods supported: 0x%x\n", eeepc->cm_supported);
1380 
1381         return 0;
1382 }
1383 
1384 static void eeepc_enable_camera(struct eeepc_laptop *eeepc)
1385 {
1386         /*
1387          * If the following call to set_acpi() fails, it's because there's no
1388          * camera so we can ignore the error.
1389          */
1390         if (get_acpi(eeepc, CM_ASL_CAMERA) == 0)
1391                 set_acpi(eeepc, CM_ASL_CAMERA, 1);
1392 }
1393 
1394 static bool eeepc_device_present;
1395 
1396 static int eeepc_acpi_add(struct acpi_device *device)
1397 {
1398         struct eeepc_laptop *eeepc;
1399         int result;
1400 
1401         pr_notice(EEEPC_LAPTOP_NAME "\n");
1402         eeepc = kzalloc(sizeof(struct eeepc_laptop), GFP_KERNEL);
1403         if (!eeepc)
1404                 return -ENOMEM;
1405         eeepc->handle = device->handle;
1406         strcpy(acpi_device_name(device), EEEPC_ACPI_DEVICE_NAME);
1407         strcpy(acpi_device_class(device), EEEPC_ACPI_CLASS);
1408         device->driver_data = eeepc;
1409         eeepc->device = device;
1410 
1411         eeepc->hotplug_disabled = hotplug_disabled;
1412 
1413         eeepc_dmi_check(eeepc);
1414 
1415         result = eeepc_acpi_init(eeepc);
1416         if (result)
1417                 goto fail_platform;
1418         eeepc_enable_camera(eeepc);
1419 
1420         /*
1421          * Register the platform device first.  It is used as a parent for the
1422          * sub-devices below.
1423          *
1424          * Note that if there are multiple instances of this ACPI device it
1425          * will bail out, because the platform device is registered with a
1426          * fixed name.  Of course it doesn't make sense to have more than one,
1427          * and machine-specific scripts find the fixed name convenient.  But
1428          * It's also good for us to exclude multiple instances because both
1429          * our hwmon and our wlan rfkill subdevice use global ACPI objects
1430          * (the EC and the wlan PCI slot respectively).
1431          */
1432         result = eeepc_platform_init(eeepc);
1433         if (result)
1434                 goto fail_platform;
1435 
1436         if (!acpi_video_backlight_support()) {
1437                 result = eeepc_backlight_init(eeepc);
1438                 if (result)
1439                         goto fail_backlight;
1440         } else {
1441                 pr_info("Backlight controlled by ACPI video driver\n");
1442         }
1443 
1444         result = eeepc_input_init(eeepc);
1445         if (result)
1446                 goto fail_input;
1447 
1448         result = eeepc_hwmon_init(eeepc);
1449         if (result)
1450                 goto fail_hwmon;
1451 
1452         result = eeepc_led_init(eeepc);
1453         if (result)
1454                 goto fail_led;
1455 
1456         result = eeepc_rfkill_init(eeepc);
1457         if (result)
1458                 goto fail_rfkill;
1459 
1460         eeepc_device_present = true;
1461         return 0;
1462 
1463 fail_rfkill:
1464         eeepc_led_exit(eeepc);
1465 fail_led:
1466 fail_hwmon:
1467         eeepc_input_exit(eeepc);
1468 fail_input:
1469         eeepc_backlight_exit(eeepc);
1470 fail_backlight:
1471         eeepc_platform_exit(eeepc);
1472 fail_platform:
1473         kfree(eeepc);
1474 
1475         return result;
1476 }
1477 
1478 static int eeepc_acpi_remove(struct acpi_device *device)
1479 {
1480         struct eeepc_laptop *eeepc = acpi_driver_data(device);
1481 
1482         eeepc_backlight_exit(eeepc);
1483         eeepc_rfkill_exit(eeepc);
1484         eeepc_input_exit(eeepc);
1485         eeepc_led_exit(eeepc);
1486         eeepc_platform_exit(eeepc);
1487 
1488         kfree(eeepc);
1489         return 0;
1490 }
1491 
1492 
1493 static const struct acpi_device_id eeepc_device_ids[] = {
1494         {EEEPC_ACPI_HID, 0},
1495         {"", 0},
1496 };
1497 MODULE_DEVICE_TABLE(acpi, eeepc_device_ids);
1498 
1499 static struct acpi_driver eeepc_acpi_driver = {
1500         .name = EEEPC_LAPTOP_NAME,
1501         .class = EEEPC_ACPI_CLASS,
1502         .owner = THIS_MODULE,
1503         .ids = eeepc_device_ids,
1504         .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
1505         .ops = {
1506                 .add = eeepc_acpi_add,
1507                 .remove = eeepc_acpi_remove,
1508                 .notify = eeepc_acpi_notify,
1509         },
1510 };
1511 
1512 
1513 static int __init eeepc_laptop_init(void)
1514 {
1515         int result;
1516 
1517         result = platform_driver_register(&platform_driver);
1518         if (result < 0)
1519                 return result;
1520 
1521         result = acpi_bus_register_driver(&eeepc_acpi_driver);
1522         if (result < 0)
1523                 goto fail_acpi_driver;
1524 
1525         if (!eeepc_device_present) {
1526                 result = -ENODEV;
1527                 goto fail_no_device;
1528         }
1529 
1530         return 0;
1531 
1532 fail_no_device:
1533         acpi_bus_unregister_driver(&eeepc_acpi_driver);
1534 fail_acpi_driver:
1535         platform_driver_unregister(&platform_driver);
1536         return result;
1537 }
1538 
1539 static void __exit eeepc_laptop_exit(void)
1540 {
1541         acpi_bus_unregister_driver(&eeepc_acpi_driver);
1542         platform_driver_unregister(&platform_driver);
1543 }
1544 
1545 module_init(eeepc_laptop_init);
1546 module_exit(eeepc_laptop_exit);
1547 

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