Linux Audio

Check our new training course

Buildroot integration, development and maintenance

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