Linux Audio

Check our new training course

Embedded Linux training

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