[go: nahoru, domu]

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