Version:  2.0.40 2.2.26 2.4.37 3.1 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

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