cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

eeepc-laptop.c (36072B)


      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	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 int 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	return 0;
   1455}
   1456
   1457
   1458static const struct acpi_device_id eeepc_device_ids[] = {
   1459	{EEEPC_ACPI_HID, 0},
   1460	{"", 0},
   1461};
   1462MODULE_DEVICE_TABLE(acpi, eeepc_device_ids);
   1463
   1464static struct acpi_driver eeepc_acpi_driver = {
   1465	.name = EEEPC_LAPTOP_NAME,
   1466	.class = EEEPC_ACPI_CLASS,
   1467	.owner = THIS_MODULE,
   1468	.ids = eeepc_device_ids,
   1469	.flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
   1470	.ops = {
   1471		.add = eeepc_acpi_add,
   1472		.remove = eeepc_acpi_remove,
   1473		.notify = eeepc_acpi_notify,
   1474	},
   1475};
   1476
   1477
   1478static int __init eeepc_laptop_init(void)
   1479{
   1480	int result;
   1481
   1482	result = platform_driver_register(&platform_driver);
   1483	if (result < 0)
   1484		return result;
   1485
   1486	result = acpi_bus_register_driver(&eeepc_acpi_driver);
   1487	if (result < 0)
   1488		goto fail_acpi_driver;
   1489
   1490	if (!eeepc_device_present) {
   1491		result = -ENODEV;
   1492		goto fail_no_device;
   1493	}
   1494
   1495	return 0;
   1496
   1497fail_no_device:
   1498	acpi_bus_unregister_driver(&eeepc_acpi_driver);
   1499fail_acpi_driver:
   1500	platform_driver_unregister(&platform_driver);
   1501	return result;
   1502}
   1503
   1504static void __exit eeepc_laptop_exit(void)
   1505{
   1506	acpi_bus_unregister_driver(&eeepc_acpi_driver);
   1507	platform_driver_unregister(&platform_driver);
   1508}
   1509
   1510module_init(eeepc_laptop_init);
   1511module_exit(eeepc_laptop_exit);