diff options
Diffstat (limited to 'drivers/platform/x86/eeepc-laptop.c')
| -rw-r--r-- | drivers/platform/x86/eeepc-laptop.c | 202 | 
1 files changed, 104 insertions, 98 deletions
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index b2edfdcdcb8..9b0c57cd1d4 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -28,8 +28,7 @@  #include <linux/hwmon.h>  #include <linux/hwmon-sysfs.h>  #include <linux/slab.h> -#include <acpi/acpi_drivers.h> -#include <acpi/acpi_bus.h> +#include <linux/acpi.h>  #include <linux/uaccess.h>  #include <linux/input.h>  #include <linux/input/sparse-keymap.h> @@ -166,7 +165,6 @@ struct eeepc_laptop {  	struct platform_device *platform_device;  	struct acpi_device *device;		/* the device we are in */ -	struct device *hwmon_device;  	struct backlight_device *backlight_device;  	struct input_dev *inputdev; @@ -190,16 +188,10 @@ struct eeepc_laptop {   */  static int write_acpi_int(acpi_handle handle, const char *method, int val)  { -	struct acpi_object_list params; -	union acpi_object in_obj;  	acpi_status status; -	params.count = 1; -	params.pointer = &in_obj; -	in_obj.type = ACPI_TYPE_INTEGER; -	in_obj.integer.value = val; +	status = acpi_execute_simple_method(handle, (char *)method, val); -	status = acpi_evaluate_object(handle, (char *)method, ¶ms, NULL);  	return (status == AE_OK ? 0 : -1);  } @@ -228,7 +220,7 @@ static int set_acpi(struct eeepc_laptop *eeepc, int cm, int value)  		return -ENODEV;  	if (write_acpi_int(eeepc->handle, method, value)) -		pr_warning("Error writing %s\n", method); +		pr_warn("Error writing %s\n", method);  	return 0;  } @@ -243,7 +235,7 @@ static int get_acpi(struct eeepc_laptop *eeepc, int cm)  		return -ENODEV;  	if (read_acpi_int(eeepc->handle, method, &value)) -		pr_warning("Error reading %s\n", method); +		pr_warn("Error reading %s\n", method);  	return value;  } @@ -261,7 +253,7 @@ static int acpi_setter_handle(struct eeepc_laptop *eeepc, int cm,  	status = acpi_get_handle(eeepc->handle, (char *)method,  				 handle);  	if (status != AE_OK) { -		pr_warning("Error finding %s\n", method); +		pr_warn("Error finding %s\n", method);  		return -ENODEV;  	}  	return 0; @@ -417,7 +409,7 @@ static ssize_t store_cpufv_disabled(struct device *dev,  	switch (value) {  	case 0:  		if (eeepc->cpufv_disabled) -			pr_warning("cpufv enabled (not officially supported " +			pr_warn("cpufv enabled (not officially supported "  				"on this model)\n");  		eeepc->cpufv_disabled = false;  		return rv; @@ -529,6 +521,15 @@ static void tpd_led_set(struct led_classdev *led_cdev,  	queue_work(eeepc->led_workqueue, &eeepc->tpd_led_work);  } +static enum led_brightness tpd_led_get(struct led_classdev *led_cdev) +{ +	struct eeepc_laptop *eeepc; + +	eeepc = container_of(led_cdev, struct eeepc_laptop, tpd_led); + +	return get_acpi(eeepc, CM_ASL_TPD); +} +  static int eeepc_led_init(struct eeepc_laptop *eeepc)  {  	int rv; @@ -543,6 +544,8 @@ static int eeepc_led_init(struct eeepc_laptop *eeepc)  	eeepc->tpd_led.name = "eeepc::touchpad";  	eeepc->tpd_led.brightness_set = tpd_led_set; +	if (get_acpi(eeepc, CM_ASL_TPD) >= 0) /* if method is available */ +	  eeepc->tpd_led.brightness_get = tpd_led_get;  	eeepc->tpd_led.max_brightness = 1;  	rv = led_classdev_register(&eeepc->platform_device->dev, @@ -557,7 +560,7 @@ static int eeepc_led_init(struct eeepc_laptop *eeepc)  static void eeepc_led_exit(struct eeepc_laptop *eeepc)  { -	if (eeepc->tpd_led.dev) +	if (!IS_ERR_OR_NULL(eeepc->tpd_led.dev))  		led_classdev_unregister(&eeepc->tpd_led);  	if (eeepc->led_workqueue)  		destroy_workqueue(eeepc->led_workqueue); @@ -574,8 +577,9 @@ static bool eeepc_wlan_rfkill_blocked(struct eeepc_laptop *eeepc)  	return true;  } -static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc) +static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc, acpi_handle handle)  { +	struct pci_dev *port;  	struct pci_dev *dev;  	struct pci_bus *bus;  	bool blocked = eeepc_wlan_rfkill_blocked(eeepc); @@ -586,28 +590,37 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc)  		rfkill_set_sw_state(eeepc->wlan_rfkill, blocked);  	mutex_lock(&eeepc->hotplug_lock); +	pci_lock_rescan_remove();  	if (eeepc->hotplug_slot) { -		bus = pci_find_bus(0, 1); -		if (!bus) { -			pr_warning("Unable to find PCI bus 1?\n"); +		port = acpi_get_pci_dev(handle); +		if (!port) { +			pr_warning("Unable to find port\n");  			goto out_unlock;  		} +		bus = port->subordinate; + +		if (!bus) { +			pr_warn("Unable to find PCI bus 1?\n"); +			goto out_put_dev; +		} +  		if (pci_bus_read_config_dword(bus, 0, PCI_VENDOR_ID, &l)) {  			pr_err("Unable to read PCI config space?\n"); -			goto out_unlock; +			goto out_put_dev;  		} +  		absent = (l == 0xffffffff);  		if (blocked != absent) { -			pr_warning("BIOS says wireless lan is %s, " -					"but the pci device is %s\n", +			pr_warn("BIOS says wireless lan is %s, " +				"but the pci device is %s\n",  				blocked ? "blocked" : "unblocked",  				absent ? "absent" : "present"); -			pr_warning("skipped wireless hotplug as probably " -					"inappropriate for this model\n"); -			goto out_unlock; +			pr_warn("skipped wireless hotplug as probably " +				"inappropriate for this model\n"); +			goto out_put_dev;  		}  		if (!blocked) { @@ -615,27 +628,40 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc)  			if (dev) {  				/* Device already present */  				pci_dev_put(dev); -				goto out_unlock; +				goto out_put_dev;  			}  			dev = pci_scan_single_device(bus, 0);  			if (dev) {  				pci_bus_assign_resources(bus); -				if (pci_bus_add_device(dev)) -					pr_err("Unable to hotplug wifi\n"); +				pci_bus_add_device(dev);  			}  		} else {  			dev = pci_get_slot(bus, 0);  			if (dev) { -				pci_remove_bus_device(dev); +				pci_stop_and_remove_bus_device(dev);  				pci_dev_put(dev);  			}  		} +out_put_dev: +		pci_dev_put(port);  	}  out_unlock: +	pci_unlock_rescan_remove();  	mutex_unlock(&eeepc->hotplug_lock);  } +static void eeepc_rfkill_hotplug_update(struct eeepc_laptop *eeepc, char *node) +{ +	acpi_status status = AE_OK; +	acpi_handle handle; + +	status = acpi_get_handle(NULL, node, &handle); + +	if (ACPI_SUCCESS(status)) +		eeepc_rfkill_hotplug(eeepc, handle); +} +  static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)  {  	struct eeepc_laptop *eeepc = data; @@ -643,7 +669,7 @@ static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)  	if (event != ACPI_NOTIFY_BUS_CHECK)  		return; -	eeepc_rfkill_hotplug(eeepc); +	eeepc_rfkill_hotplug(eeepc, handle);  }  static int eeepc_register_rfkill_notifier(struct eeepc_laptop *eeepc, @@ -660,7 +686,13 @@ static int eeepc_register_rfkill_notifier(struct eeepc_laptop *eeepc,  						     eeepc_rfkill_notify,  						     eeepc);  		if (ACPI_FAILURE(status)) -			pr_warning("Failed to register notify on %s\n", node); +			pr_warn("Failed to register notify on %s\n", node); + +		/* +		 * Refresh pci hotplug in case the rfkill state was +		 * changed during setup. +		 */ +		eeepc_rfkill_hotplug(eeepc, handle);  	} else  		return -ENODEV; @@ -682,6 +714,12 @@ static void eeepc_unregister_rfkill_notifier(struct eeepc_laptop *eeepc,  		if (ACPI_FAILURE(status))  			pr_err("Error removing rfkill notify handler %s\n",  				node); +			/* +			 * Refresh pci hotplug in case the rfkill +			 * state was changed after +			 * eeepc_unregister_rfkill_notifier() +			 */ +		eeepc_rfkill_hotplug(eeepc, handle);  	}  } @@ -805,11 +843,7 @@ static void eeepc_rfkill_exit(struct eeepc_laptop *eeepc)  		rfkill_destroy(eeepc->wlan_rfkill);  		eeepc->wlan_rfkill = NULL;  	} -	/* -	 * Refresh pci hotplug in case the rfkill state was changed after -	 * eeepc_unregister_rfkill_notifier() -	 */ -	eeepc_rfkill_hotplug(eeepc); +  	if (eeepc->hotplug_slot)  		pci_hp_deregister(eeepc->hotplug_slot); @@ -878,11 +912,6 @@ static int eeepc_rfkill_init(struct eeepc_laptop *eeepc)  	eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P5");  	eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P6");  	eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P7"); -	/* -	 * Refresh pci hotplug in case the rfkill state was changed during -	 * setup. -	 */ -	eeepc_rfkill_hotplug(eeepc);  exit:  	if (result && result != -ENODEV) @@ -917,8 +946,11 @@ static int eeepc_hotk_restore(struct device *device)  	struct eeepc_laptop *eeepc = dev_get_drvdata(device);  	/* Refresh both wlan rfkill state and pci hotplug */ -	if (eeepc->wlan_rfkill) -		eeepc_rfkill_hotplug(eeepc); +	if (eeepc->wlan_rfkill) { +		eeepc_rfkill_hotplug_update(eeepc, "\\_SB.PCI0.P0P5"); +		eeepc_rfkill_hotplug_update(eeepc, "\\_SB.PCI0.P0P6"); +		eeepc_rfkill_hotplug_update(eeepc, "\\_SB.PCI0.P0P7"); +	}  	if (eeepc->bluetooth_rfkill)  		rfkill_set_sw_state(eeepc->bluetooth_rfkill, @@ -968,7 +1000,7 @@ static int eeepc_get_fan_pwm(void)  static void eeepc_set_fan_pwm(int value)  { -	value = SENSORS_LIMIT(value, 0, 255); +	value = clamp_val(value, 0, 255);  	value = value * 100 / 255;  	ec_write(EEEPC_EC_FAN_PWM, value);  } @@ -1034,7 +1066,7 @@ static ssize_t show_sys_hwmon(int (*get)(void), char *buf)  	{								\  		return store_sys_hwmon(_get, buf, count);		\  	}								\ -	static SENSOR_DEVICE_ATTR(_name, _mode, show_##_name, store_##_name, 0); +	static DEVICE_ATTR(_name, _mode, show_##_name, store_##_name);  EEEPC_CREATE_SENSOR_ATTR(fan1_input, S_IRUGO, eeepc_get_fan_rpm, NULL);  EEEPC_CREATE_SENSOR_ATTR(pwm1, S_IRUGO | S_IWUSR, @@ -1042,55 +1074,26 @@ EEEPC_CREATE_SENSOR_ATTR(pwm1, S_IRUGO | S_IWUSR,  EEEPC_CREATE_SENSOR_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,  			 eeepc_get_fan_ctrl, eeepc_set_fan_ctrl); -static ssize_t -show_name(struct device *dev, struct device_attribute *attr, char *buf) -{ -	return sprintf(buf, "eeepc\n"); -} -static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0); - -static struct attribute *hwmon_attributes[] = { -	&sensor_dev_attr_pwm1.dev_attr.attr, -	&sensor_dev_attr_fan1_input.dev_attr.attr, -	&sensor_dev_attr_pwm1_enable.dev_attr.attr, -	&sensor_dev_attr_name.dev_attr.attr, +static struct attribute *hwmon_attrs[] = { +	&dev_attr_pwm1.attr, +	&dev_attr_fan1_input.attr, +	&dev_attr_pwm1_enable.attr,  	NULL  }; - -static struct attribute_group hwmon_attribute_group = { -	.attrs = hwmon_attributes -}; - -static void eeepc_hwmon_exit(struct eeepc_laptop *eeepc) -{ -	struct device *hwmon; - -	hwmon = eeepc->hwmon_device; -	if (!hwmon) -		return; -	sysfs_remove_group(&hwmon->kobj, -			   &hwmon_attribute_group); -	hwmon_device_unregister(hwmon); -	eeepc->hwmon_device = NULL; -} +ATTRIBUTE_GROUPS(hwmon);  static int eeepc_hwmon_init(struct eeepc_laptop *eeepc)  { +	struct device *dev = &eeepc->platform_device->dev;  	struct device *hwmon; -	int result; -	hwmon = hwmon_device_register(&eeepc->platform_device->dev); +	hwmon = devm_hwmon_device_register_with_groups(dev, "eeepc", NULL, +						       hwmon_groups);  	if (IS_ERR(hwmon)) {  		pr_err("Could not register eeepc hwmon device\n"); -		eeepc->hwmon_device = NULL;  		return PTR_ERR(hwmon);  	} -	eeepc->hwmon_device = hwmon; -	result = sysfs_create_group(&hwmon->kobj, -				    &hwmon_attribute_group); -	if (result) -		eeepc_hwmon_exit(eeepc); -	return result; +	return 0;  }  /* @@ -1115,7 +1118,7 @@ static int update_bl_status(struct backlight_device *bd)  	return set_brightness(bd, bd->props.brightness);  } -static struct backlight_ops eeepcbl_ops = { +static const struct backlight_ops eeepcbl_ops = {  	.get_brightness = read_brightness,  	.update_status = update_bl_status,  }; @@ -1136,6 +1139,7 @@ static int eeepc_backlight_init(struct eeepc_laptop *eeepc)  	struct backlight_device *bd;  	memset(&props, 0, sizeof(struct backlight_properties)); +	props.type = BACKLIGHT_PLATFORM;  	props.max_brightness = 15;  	bd = backlight_device_register(EEEPC_LAPTOP_FILE,  				       &eeepc->platform_device->dev, eeepc, @@ -1169,10 +1173,8 @@ static int eeepc_input_init(struct eeepc_laptop *eeepc)  	int error;  	input = input_allocate_device(); -	if (!input) { -		pr_info("Unable to allocate input device\n"); +	if (!input)  		return -ENOMEM; -	}  	input->name = "Asus EeePC extra buttons";  	input->phys = EEEPC_LAPTOP_FILE "/input0"; @@ -1213,6 +1215,14 @@ static void eeepc_input_exit(struct eeepc_laptop *eeepc)  /*   * ACPI driver   */ +static void eeepc_input_notify(struct eeepc_laptop *eeepc, int event) +{ +	if (!eeepc->inputdev) +		return ; +	if (!sparse_keymap_report_event(eeepc->inputdev, event, 1, true)) +		pr_info("Unknown key %x pressed\n", event); +} +  static void eeepc_acpi_notify(struct acpi_device *device, u32 event)  {  	struct eeepc_laptop *eeepc = acpi_driver_data(device); @@ -1221,7 +1231,6 @@ static void eeepc_acpi_notify(struct acpi_device *device, u32 event)  	if (event > ACPI_MAX_SYS_NOTIFY)  		return;  	count = eeepc->event_count[event % 128]++; -	acpi_bus_generate_proc_event(device, event, count);  	acpi_bus_generate_netlink_event(device->pnp.device_class,  					dev_name(&device->dev), event,  					count); @@ -1249,12 +1258,11 @@ static void eeepc_acpi_notify(struct acpi_device *device, u32 event)  				* event will be desired value (or else ignored)  				*/  			} -			sparse_keymap_report_event(eeepc->inputdev, event, -						   1, true); +			eeepc_input_notify(eeepc, event);  		}  	} else {  		/* Everything else is a bona-fide keypress event */ -		sparse_keymap_report_event(eeepc->inputdev, event, 1, true); +		eeepc_input_notify(eeepc, event);  	}  } @@ -1310,7 +1318,7 @@ static void cmsg_quirk(struct eeepc_laptop *eeepc, int cm, const char *name)  {  	int dummy; -	/* Some BIOSes do not report cm although it is avaliable. +	/* Some BIOSes do not report cm although it is available.  	   Check if cm_getv[cm] works and, if yes, assume cm should be set. */  	if (!(eeepc->cm_supported & (1 << cm))  	    && !read_acpi_int(eeepc->handle, cm_getv[cm], &dummy)) { @@ -1328,7 +1336,7 @@ static void cmsg_quirks(struct eeepc_laptop *eeepc)  	cmsg_quirk(eeepc, CM_ASL_TPD, "TPD");  } -static int __devinit eeepc_acpi_init(struct eeepc_laptop *eeepc) +static int eeepc_acpi_init(struct eeepc_laptop *eeepc)  {  	unsigned int init_flags;  	int result; @@ -1360,7 +1368,7 @@ static int __devinit eeepc_acpi_init(struct eeepc_laptop *eeepc)  	return 0;  } -static void __devinit eeepc_enable_camera(struct eeepc_laptop *eeepc) +static void eeepc_enable_camera(struct eeepc_laptop *eeepc)  {  	/*  	 * If the following call to set_acpi() fails, it's because there's no @@ -1372,7 +1380,7 @@ static void __devinit eeepc_enable_camera(struct eeepc_laptop *eeepc)  static bool eeepc_device_present; -static int __devinit eeepc_acpi_add(struct acpi_device *device) +static int eeepc_acpi_add(struct acpi_device *device)  {  	struct eeepc_laptop *eeepc;  	int result; @@ -1441,7 +1449,6 @@ static int __devinit eeepc_acpi_add(struct acpi_device *device)  fail_rfkill:  	eeepc_led_exit(eeepc);  fail_led: -	eeepc_hwmon_exit(eeepc);  fail_hwmon:  	eeepc_input_exit(eeepc);  fail_input: @@ -1454,14 +1461,13 @@ fail_platform:  	return result;  } -static int eeepc_acpi_remove(struct acpi_device *device, int type) +static int eeepc_acpi_remove(struct acpi_device *device)  {  	struct eeepc_laptop *eeepc = acpi_driver_data(device);  	eeepc_backlight_exit(eeepc);  	eeepc_rfkill_exit(eeepc);  	eeepc_input_exit(eeepc); -	eeepc_hwmon_exit(eeepc);  	eeepc_led_exit(eeepc);  	eeepc_platform_exit(eeepc);  | 
