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