Linux Audio

Check our new training course

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