diff options
Diffstat (limited to 'drivers/platform/x86/asus-wmi.c')
-rw-r--r-- | drivers/platform/x86/asus-wmi.c | 534 |
1 files changed, 324 insertions, 210 deletions
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index ca28d27dae63..821b08e01635 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -26,6 +26,7 @@ #include <linux/rfkill.h> #include <linux/pci.h> #include <linux/pci_hotplug.h> +#include <linux/power_supply.h> #include <linux/hwmon.h> #include <linux/hwmon-sysfs.h> #include <linux/debugfs.h> @@ -35,6 +36,8 @@ #include <linux/thermal.h> #include <linux/acpi.h> #include <linux/dmi.h> + +#include <acpi/battery.h> #include <acpi/video.h> #include "asus-wmi.h" @@ -65,6 +68,9 @@ MODULE_LICENSE("GPL"); #define ASUS_FAN_MFUN 0x13 #define ASUS_FAN_SFUN_READ 0x06 #define ASUS_FAN_SFUN_WRITE 0x07 + +/* Based on standard hwmon pwmX_enable values */ +#define ASUS_FAN_CTRL_FULLSPEED 0 #define ASUS_FAN_CTRL_MANUAL 1 #define ASUS_FAN_CTRL_AUTO 2 @@ -120,7 +126,7 @@ struct agfn_args { } __packed; /* struct used for calling fan read and write methods */ -struct fan_args { +struct agfn_fan_args { struct agfn_args agfn; /* common fields */ u8 fan; /* fan number: 0: set auto mode 1: 1st fan */ u32 speed; /* read: RPM/100 - write: 0-255 */ @@ -148,6 +154,12 @@ struct asus_rfkill { u32 dev_id; }; +enum fan_type { + FAN_TYPE_NONE = 0, + FAN_TYPE_AGFN, /* deprecated on newer platforms */ + FAN_TYPE_SPEC83, /* starting in Spec 8.3, use CPU_FAN_CTRL */ +}; + struct asus_wmi { int dsts_id; int spec; @@ -178,14 +190,17 @@ struct asus_wmi { struct asus_rfkill gps; struct asus_rfkill uwb; - bool asus_hwmon_fan_manual_mode; - int asus_hwmon_num_fans; - int asus_hwmon_pwm; + enum fan_type fan_type; + int fan_pwm_mode; + int agfn_pwm; bool fan_boost_mode_available; u8 fan_boost_mode_mask; u8 fan_boost_mode; + // The RSOC controls the maximum charging percentage. + bool battery_rsoc_available; + struct hotplug_slot hotplug_slot; struct mutex hotplug_lock; struct mutex wmi_lock; @@ -292,12 +307,11 @@ static int asus_wmi_evaluate_method_agfn(const struct acpi_buffer args) * Copy to dma capable address otherwise memory corruption occurs as * bios has to be able to access it. */ - input.pointer = kzalloc(args.length, GFP_DMA | GFP_KERNEL); + input.pointer = kmemdup(args.pointer, args.length, GFP_DMA | GFP_KERNEL); input.length = args.length; if (!input.pointer) return -ENOMEM; phys_addr = virt_to_phys(input.pointer); - memcpy(input.pointer, args.pointer, args.length); status = asus_wmi_evaluate_method(ASUS_WMI_METHODID_AGFN, phys_addr, 0, &retval); @@ -331,7 +345,6 @@ static int asus_wmi_get_devstate_bits(struct asus_wmi *asus, int err; err = asus_wmi_get_devstate(asus, dev_id, &retval); - if (err < 0) return err; @@ -352,6 +365,105 @@ static int asus_wmi_get_devstate_simple(struct asus_wmi *asus, u32 dev_id) ASUS_WMI_DSTS_STATUS_BIT); } +static bool asus_wmi_dev_is_present(struct asus_wmi *asus, u32 dev_id) +{ + u32 retval; + int status = asus_wmi_get_devstate(asus, dev_id, &retval); + + return status == 0 && (retval & ASUS_WMI_DSTS_PRESENCE_BIT); +} + +/* Battery ********************************************************************/ + +/* The battery maximum charging percentage */ +static int charge_end_threshold; + +static ssize_t charge_control_end_threshold_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int value, ret, rv; + + ret = kstrtouint(buf, 10, &value); + if (ret) + return ret; + + if (value < 0 || value > 100) + return -EINVAL; + + ret = asus_wmi_set_devstate(ASUS_WMI_DEVID_RSOC, value, &rv); + if (ret) + return ret; + + if (rv != 1) + return -EIO; + + /* There isn't any method in the DSDT to read the threshold, so we + * save the threshold. + */ + charge_end_threshold = value; + return count; +} + +static ssize_t charge_control_end_threshold_show(struct device *device, + struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d\n", charge_end_threshold); +} + +static DEVICE_ATTR_RW(charge_control_end_threshold); + +static int asus_wmi_battery_add(struct power_supply *battery) +{ + /* The WMI method does not provide a way to specific a battery, so we + * just assume it is the first battery. + */ + if (strcmp(battery->desc->name, "BAT0") != 0) + return -ENODEV; + + if (device_create_file(&battery->dev, + &dev_attr_charge_control_end_threshold)) + return -ENODEV; + + /* The charge threshold is only reset when the system is power cycled, + * and we can't get the current threshold so let set it to 100% when + * a battery is added. + */ + asus_wmi_set_devstate(ASUS_WMI_DEVID_RSOC, 100, NULL); + charge_end_threshold = 100; + + return 0; +} + +static int asus_wmi_battery_remove(struct power_supply *battery) +{ + device_remove_file(&battery->dev, + &dev_attr_charge_control_end_threshold); + return 0; +} + +static struct acpi_battery_hook battery_hook = { + .add_battery = asus_wmi_battery_add, + .remove_battery = asus_wmi_battery_remove, + .name = "ASUS Battery Extension", +}; + +static void asus_wmi_battery_init(struct asus_wmi *asus) +{ + asus->battery_rsoc_available = false; + if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_RSOC)) { + asus->battery_rsoc_available = true; + battery_hook_register(&battery_hook); + } +} + +static void asus_wmi_battery_exit(struct asus_wmi *asus) +{ + if (asus->battery_rsoc_available) + battery_hook_unregister(&battery_hook); +} + /* LEDs ***********************************************************************/ /* @@ -427,15 +539,14 @@ static int kbd_led_read(struct asus_wmi *asus, int *level, int *env) if (retval == 0x8000) retval = 0; - if (retval >= 0) { - if (level) - *level = retval & 0x7F; - if (env) - *env = (retval >> 8) & 0x7F; - retval = 0; - } + if (retval < 0) + return retval; - return retval; + if (level) + *level = retval & 0x7F; + if (env) + *env = (retval >> 8) & 0x7F; + return 0; } static void do_kbd_led_set(struct led_classdev *led_cdev, int value) @@ -446,12 +557,7 @@ static void do_kbd_led_set(struct led_classdev *led_cdev, int value) asus = container_of(led_cdev, struct asus_wmi, kbd_led); max_level = asus->kbd_led.max_brightness; - if (value > max_level) - value = max_level; - else if (value < 0) - value = 0; - - asus->kbd_led_wk = value; + asus->kbd_led_wk = clamp_val(value, 0, max_level); kbd_led_update(asus); } @@ -481,7 +587,6 @@ static enum led_brightness kbd_led_get(struct led_classdev *led_cdev) asus = container_of(led_cdev, struct asus_wmi, kbd_led); retval = kbd_led_read(asus, &value, NULL); - if (retval < 0) return retval; @@ -497,15 +602,6 @@ static int wlan_led_unknown_state(struct asus_wmi *asus) return result & ASUS_WMI_DSTS_UNKNOWN_BIT; } -static int wlan_led_presence(struct asus_wmi *asus) -{ - u32 result; - - asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WIRELESS_LED, &result); - - return result & ASUS_WMI_DSTS_PRESENCE_BIT; -} - static void wlan_led_update(struct work_struct *work) { int ctrl_param; @@ -572,15 +668,6 @@ static enum led_brightness lightbar_led_get(struct led_classdev *led_cdev) return result & ASUS_WMI_DSTS_LIGHTBAR_MASK; } -static int lightbar_led_presence(struct asus_wmi *asus) -{ - u32 result; - - asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_LIGHTBAR, &result); - - return result & ASUS_WMI_DSTS_PRESENCE_BIT; -} - static void asus_wmi_led_exit(struct asus_wmi *asus) { if (!IS_ERR_OR_NULL(asus->kbd_led.dev)) @@ -631,7 +718,8 @@ static int asus_wmi_led_init(struct asus_wmi *asus) goto error; } - if (wlan_led_presence(asus) && (asus->driver->quirks->wapf > 0)) { + if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_WIRELESS_LED) + && (asus->driver->quirks->wapf > 0)) { INIT_WORK(&asus->wlan_led_work, wlan_led_update); asus->wlan_led.name = "asus::wlan"; @@ -648,7 +736,7 @@ static int asus_wmi_led_init(struct asus_wmi *asus) goto error; } - if (lightbar_led_presence(asus)) { + if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_LIGHTBAR)) { INIT_WORK(&asus->lightbar_led_work, lightbar_led_update); asus->lightbar_led.name = "asus::lightbar"; @@ -771,16 +859,14 @@ static int asus_register_rfkill_notifier(struct asus_wmi *asus, char *node) acpi_handle handle; status = acpi_get_handle(NULL, node, &handle); - - if (ACPI_SUCCESS(status)) { - status = acpi_install_notify_handler(handle, - ACPI_SYSTEM_NOTIFY, - asus_rfkill_notify, asus); - if (ACPI_FAILURE(status)) - pr_warn("Failed to register notify on %s\n", node); - } else + if (ACPI_FAILURE(status)) return -ENODEV; + status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, + asus_rfkill_notify, asus); + if (ACPI_FAILURE(status)) + pr_warn("Failed to register notify on %s\n", node); + return 0; } @@ -790,15 +876,13 @@ static void asus_unregister_rfkill_notifier(struct asus_wmi *asus, char *node) acpi_handle handle; status = acpi_get_handle(NULL, node, &handle); + if (ACPI_FAILURE(status)) + return; - if (ACPI_SUCCESS(status)) { - status = acpi_remove_notify_handler(handle, - ACPI_SYSTEM_NOTIFY, - asus_rfkill_notify); - if (ACPI_FAILURE(status)) - pr_err("Error removing rfkill notify handler %s\n", - node); - } + status = acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY, + asus_rfkill_notify); + if (ACPI_FAILURE(status)) + pr_err("Error removing rfkill notify handler %s\n", node); } static int asus_get_adapter_status(struct hotplug_slot *hotplug_slot, @@ -1126,10 +1210,10 @@ static void asus_wmi_set_als(void) /* Hwmon device ***************************************************************/ -static int asus_hwmon_agfn_fan_speed_read(struct asus_wmi *asus, int fan, +static int asus_agfn_fan_speed_read(struct asus_wmi *asus, int fan, int *speed) { - struct fan_args args = { + struct agfn_fan_args args = { .agfn.len = sizeof(args), .agfn.mfun = ASUS_FAN_MFUN, .agfn.sfun = ASUS_FAN_SFUN_READ, @@ -1153,10 +1237,10 @@ static int asus_hwmon_agfn_fan_speed_read(struct asus_wmi *asus, int fan, return 0; } -static int asus_hwmon_agfn_fan_speed_write(struct asus_wmi *asus, int fan, +static int asus_agfn_fan_speed_write(struct asus_wmi *asus, int fan, int *speed) { - struct fan_args args = { + struct agfn_fan_args args = { .agfn.len = sizeof(args), .agfn.mfun = ASUS_FAN_MFUN, .agfn.sfun = ASUS_FAN_SFUN_WRITE, @@ -1176,7 +1260,7 @@ static int asus_hwmon_agfn_fan_speed_write(struct asus_wmi *asus, int fan, return -ENXIO; if (speed && fan == 1) - asus->asus_hwmon_pwm = *speed; + asus->agfn_pwm = *speed; return 0; } @@ -1185,77 +1269,60 @@ static int asus_hwmon_agfn_fan_speed_write(struct asus_wmi *asus, int fan, * Check if we can read the speed of one fan. If true we assume we can also * control it. */ -static int asus_hwmon_get_fan_number(struct asus_wmi *asus, int *num_fans) +static bool asus_wmi_has_agfn_fan(struct asus_wmi *asus) { int status; - int speed = 0; + int speed; + u32 value; - *num_fans = 0; + status = asus_agfn_fan_speed_read(asus, 1, &speed); + if (status != 0) + return false; - status = asus_hwmon_agfn_fan_speed_read(asus, 1, &speed); - if (!status) - *num_fans = 1; + status = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_FAN_CTRL, &value); + if (status != 0) + return false; - return 0; + /* + * We need to find a better way, probably using sfun, + * bits or spec ... + * Currently we disable it if: + * - ASUS_WMI_UNSUPPORTED_METHOD is returned + * - reverved bits are non-zero + * - sfun and presence bit are not set + */ + return !(value == ASUS_WMI_UNSUPPORTED_METHOD || value & 0xFFF80000 + || (!asus->sfun && !(value & ASUS_WMI_DSTS_PRESENCE_BIT))); } -static int asus_hwmon_fan_set_auto(struct asus_wmi *asus) +static int asus_fan_set_auto(struct asus_wmi *asus) { int status; + u32 retval; - status = asus_hwmon_agfn_fan_speed_write(asus, 0, NULL); - if (status) - return -ENXIO; - - asus->asus_hwmon_fan_manual_mode = false; - - return 0; -} + switch (asus->fan_type) { + case FAN_TYPE_SPEC83: + status = asus_wmi_set_devstate(ASUS_WMI_DEVID_CPU_FAN_CTRL, + 0, &retval); + if (status) + return status; -static int asus_hwmon_fan_rpm_show(struct device *dev, int fan) -{ - struct asus_wmi *asus = dev_get_drvdata(dev); - int value; - int ret; + if (retval != 1) + return -EIO; + break; - /* no speed readable on manual mode */ - if (asus->asus_hwmon_fan_manual_mode) - return -ENXIO; + case FAN_TYPE_AGFN: + status = asus_agfn_fan_speed_write(asus, 0, NULL); + if (status) + return -ENXIO; + break; - ret = asus_hwmon_agfn_fan_speed_read(asus, fan+1, &value); - if (ret) { - pr_warn("reading fan speed failed: %d\n", ret); + default: return -ENXIO; } - return value; -} -static void asus_hwmon_pwm_show(struct asus_wmi *asus, int fan, int *value) -{ - int err; - - if (asus->asus_hwmon_pwm >= 0) { - *value = asus->asus_hwmon_pwm; - return; - } - - err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_FAN_CTRL, value); - if (err < 0) - return; - - *value &= 0xFF; - - if (*value == 1) /* Low Speed */ - *value = 85; - else if (*value == 2) - *value = 170; - else if (*value == 3) - *value = 255; - else if (*value) { - pr_err("Unknown fan speed %#x\n", *value); - *value = -1; - } + return 0; } static ssize_t pwm1_show(struct device *dev, @@ -1263,9 +1330,33 @@ static ssize_t pwm1_show(struct device *dev, char *buf) { struct asus_wmi *asus = dev_get_drvdata(dev); + int err; int value; - asus_hwmon_pwm_show(asus, 0, &value); + /* If we already set a value then just return it */ + if (asus->agfn_pwm >= 0) + return sprintf(buf, "%d\n", asus->agfn_pwm); + + /* + * If we haven't set already set a value through the AGFN interface, + * we read a current value through the (now-deprecated) FAN_CTRL device. + */ + err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_FAN_CTRL, &value); + if (err < 0) + return err; + + value &= 0xFF; + + if (value == 1) /* Low Speed */ + value = 85; + else if (value == 2) + value = 170; + else if (value == 3) + value = 255; + else if (value) { + pr_err("Unknown fan speed %#x\n", value); + value = -1; + } return sprintf(buf, "%d\n", value); } @@ -1279,17 +1370,16 @@ static ssize_t pwm1_store(struct device *dev, int ret; ret = kstrtouint(buf, 10, &value); - if (ret) return ret; value = clamp(value, 0, 255); - state = asus_hwmon_agfn_fan_speed_write(asus, 1, &value); + state = asus_agfn_fan_speed_write(asus, 1, &value); if (state) pr_warn("Setting fan speed failed: %d\n", state); else - asus->asus_hwmon_fan_manual_mode = true; + asus->fan_pwm_mode = ASUS_FAN_CTRL_MANUAL; return count; } @@ -1298,10 +1388,37 @@ static ssize_t fan1_input_show(struct device *dev, struct device_attribute *attr, char *buf) { - int value = asus_hwmon_fan_rpm_show(dev, 0); + struct asus_wmi *asus = dev_get_drvdata(dev); + int value; + int ret; - return sprintf(buf, "%d\n", value < 0 ? -1 : value*100); + switch (asus->fan_type) { + case FAN_TYPE_SPEC83: + ret = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_CPU_FAN_CTRL, + &value); + if (ret < 0) + return ret; + + value &= 0xffff; + break; + + case FAN_TYPE_AGFN: + /* no speed readable on manual mode */ + if (asus->fan_pwm_mode == ASUS_FAN_CTRL_MANUAL) + return -ENXIO; + + ret = asus_agfn_fan_speed_read(asus, 1, &value); + if (ret) { + pr_warn("reading fan speed failed: %d\n", ret); + return -ENXIO; + } + break; + + default: + return -ENXIO; + } + return sprintf(buf, "%d\n", value < 0 ? -1 : value*100); } static ssize_t pwm1_enable_show(struct device *dev, @@ -1310,10 +1427,16 @@ static ssize_t pwm1_enable_show(struct device *dev, { struct asus_wmi *asus = dev_get_drvdata(dev); - if (asus->asus_hwmon_fan_manual_mode) - return sprintf(buf, "%d\n", ASUS_FAN_CTRL_MANUAL); - - return sprintf(buf, "%d\n", ASUS_FAN_CTRL_AUTO); + /* + * Just read back the cached pwm mode. + * + * For the CPU_FAN device, the spec indicates that we should be + * able to read the device status and consult bit 19 to see if we + * are in Full On or Automatic mode. However, this does not work + * in practice on X532FL at least (the bit is always 0) and there's + * also nothing in the DSDT to indicate that this behaviour exists. + */ + return sprintf(buf, "%d\n", asus->fan_pwm_mode); } static ssize_t pwm1_enable_store(struct device *dev, @@ -1323,21 +1446,50 @@ static ssize_t pwm1_enable_store(struct device *dev, struct asus_wmi *asus = dev_get_drvdata(dev); int status = 0; int state; + int value; int ret; + u32 retval; ret = kstrtouint(buf, 10, &state); - if (ret) return ret; - if (state == ASUS_FAN_CTRL_MANUAL) - asus->asus_hwmon_fan_manual_mode = true; - else - status = asus_hwmon_fan_set_auto(asus); + if (asus->fan_type == FAN_TYPE_SPEC83) { + switch (state) { /* standard documented hwmon values */ + case ASUS_FAN_CTRL_FULLSPEED: + value = 1; + break; + case ASUS_FAN_CTRL_AUTO: + value = 0; + break; + default: + return -EINVAL; + } - if (status) - return status; + ret = asus_wmi_set_devstate(ASUS_WMI_DEVID_CPU_FAN_CTRL, + value, &retval); + if (ret) + return ret; + + if (retval != 1) + return -EIO; + } else if (asus->fan_type == FAN_TYPE_AGFN) { + switch (state) { + case ASUS_FAN_CTRL_MANUAL: + break; + + case ASUS_FAN_CTRL_AUTO: + status = asus_fan_set_auto(asus); + if (status) + return status; + break; + default: + return -EINVAL; + } + } + + asus->fan_pwm_mode = state; return count; } @@ -1357,7 +1509,6 @@ static ssize_t asus_hwmon_temp1(struct device *dev, int err; err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_THERMAL_CTRL, &value); - if (err < 0) return err; @@ -1390,59 +1541,33 @@ static umode_t asus_hwmon_sysfs_is_visible(struct kobject *kobj, { struct device *dev = container_of(kobj, struct device, kobj); struct asus_wmi *asus = dev_get_drvdata(dev->parent); - int dev_id = -1; - int fan_attr = -1; u32 value = ASUS_WMI_UNSUPPORTED_METHOD; - bool ok = true; - if (attr == &dev_attr_pwm1.attr) - dev_id = ASUS_WMI_DEVID_FAN_CTRL; - else if (attr == &dev_attr_temp1_input.attr) - dev_id = ASUS_WMI_DEVID_THERMAL_CTRL; - - - if (attr == &dev_attr_fan1_input.attr + if (attr == &dev_attr_pwm1.attr) { + if (asus->fan_type != FAN_TYPE_AGFN) + return 0; + } else if (attr == &dev_attr_fan1_input.attr || attr == &dev_attr_fan1_label.attr - || attr == &dev_attr_pwm1.attr || attr == &dev_attr_pwm1_enable.attr) { - fan_attr = 1; - } - - if (dev_id != -1) { - int err = asus_wmi_get_devstate(asus, dev_id, &value); + if (asus->fan_type == FAN_TYPE_NONE) + return 0; + } else if (attr == &dev_attr_temp1_input.attr) { + int err = asus_wmi_get_devstate(asus, + ASUS_WMI_DEVID_THERMAL_CTRL, + &value); - if (err < 0 && fan_attr == -1) + if (err < 0) return 0; /* can't return negative here */ - } - if (dev_id == ASUS_WMI_DEVID_FAN_CTRL) { - /* - * We need to find a better way, probably using sfun, - * bits or spec ... - * Currently we disable it if: - * - ASUS_WMI_UNSUPPORTED_METHOD is returned - * - reverved bits are non-zero - * - sfun and presence bit are not set - */ - if (value == ASUS_WMI_UNSUPPORTED_METHOD || value & 0xFFF80000 - || (!asus->sfun && !(value & ASUS_WMI_DSTS_PRESENCE_BIT))) - ok = false; - else - ok = fan_attr <= asus->asus_hwmon_num_fans; - } else if (dev_id == ASUS_WMI_DEVID_THERMAL_CTRL) { /* * If the temperature value in deci-Kelvin is near the absolute * zero temperature, something is clearly wrong */ if (value == 0 || value == 1) - ok = false; - } else if (fan_attr <= asus->asus_hwmon_num_fans && fan_attr != -1) { - ok = true; - } else { - ok = false; + return 0; } - return ok ? attr->mode : 0; + return attr->mode; } static const struct attribute_group hwmon_attribute_group = { @@ -1468,20 +1593,19 @@ static int asus_wmi_hwmon_init(struct asus_wmi *asus) static int asus_wmi_fan_init(struct asus_wmi *asus) { - int status; + asus->fan_type = FAN_TYPE_NONE; + asus->agfn_pwm = -1; - asus->asus_hwmon_pwm = -1; - asus->asus_hwmon_num_fans = -1; - asus->asus_hwmon_fan_manual_mode = false; + if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_CPU_FAN_CTRL)) + asus->fan_type = FAN_TYPE_SPEC83; + else if (asus_wmi_has_agfn_fan(asus)) + asus->fan_type = FAN_TYPE_AGFN; - status = asus_hwmon_get_fan_number(asus, &asus->asus_hwmon_num_fans); - if (status) { - asus->asus_hwmon_num_fans = 0; - pr_warn("Could not determine number of fans: %d\n", status); - return -ENXIO; - } + if (asus->fan_type == FAN_TYPE_NONE) + return -ENODEV; - pr_info("Number of fans: %d\n", asus->asus_hwmon_num_fans); + asus_fan_set_auto(asus); + asus->fan_pwm_mode = ASUS_FAN_CTRL_AUTO; return 0; } @@ -1523,7 +1647,6 @@ static int fan_boost_mode_write(struct asus_wmi *asus) pr_info("Set fan boost mode: %u\n", value); err = asus_wmi_set_devstate(ASUS_WMI_DEVID_FAN_BOOST_MODE, value, &retval); - if (err) { pr_warn("Failed to set fan boost mode: %d\n", err); return err; @@ -1606,6 +1729,7 @@ static DEVICE_ATTR_RW(fan_boost_mode); static int read_backlight_power(struct asus_wmi *asus) { int ret; + if (asus->driver->quirks->store_backlight_power) ret = !asus->driver->panel_power; else @@ -1624,7 +1748,6 @@ static int read_brightness_max(struct asus_wmi *asus) int err; err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_BRIGHTNESS, &retval); - if (err < 0) return err; @@ -1644,7 +1767,6 @@ static int read_brightness(struct backlight_device *bd) int err; err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_BRIGHTNESS, &retval); - if (err < 0) return err; @@ -1734,7 +1856,6 @@ static int asus_wmi_backlight_init(struct asus_wmi *asus) return max; power = read_backlight_power(asus); - if (power == -ENODEV) power = FB_BLANK_UNBLANK; else if (power < 0) @@ -1900,7 +2021,6 @@ static void asus_wmi_notify(u32 value, void *context) for (i = 0; i < WMI_EVENT_QUEUE_SIZE + 1; i++) { code = asus_wmi_get_event_code(value); - if (code < 0) { pr_warn("Failed to get notify code: %d\n", code); return; @@ -1929,7 +2049,6 @@ static int asus_wmi_notify_queue_flush(struct asus_wmi *asus) for (i = 0; i < WMI_EVENT_QUEUE_SIZE + 1; i++) { code = asus_wmi_get_event_code(WMI_EVENT_VALUE_ATK); - if (code < 0) { pr_warn("Failed to get event during flush: %d\n", code); return code; @@ -1945,32 +2064,25 @@ static int asus_wmi_notify_queue_flush(struct asus_wmi *asus) /* Sysfs **********************************************************************/ -static int parse_arg(const char *buf, unsigned long count, int *val) -{ - if (!count) - return 0; - if (sscanf(buf, "%i", val) != 1) - return -EINVAL; - return count; -} - static ssize_t store_sys_wmi(struct asus_wmi *asus, int devid, const char *buf, size_t count) { u32 retval; - int rv, err, value; + int err, value; value = asus_wmi_get_devstate_simple(asus, devid); if (value < 0) return value; - rv = parse_arg(buf, count, &value); - err = asus_wmi_set_devstate(devid, value, &retval); + err = kstrtoint(buf, 0, &value); + if (err) + return err; + err = asus_wmi_set_devstate(devid, value, &retval); if (err < 0) return err; - return rv; + return count; } static ssize_t show_sys_wmi(struct asus_wmi *asus, int devid, char *buf) @@ -2019,8 +2131,10 @@ static ssize_t cpufv_store(struct device *dev, struct device_attribute *attr, { int value, rv; - if (!count || sscanf(buf, "%i", &value) != 1) - return -EINVAL; + rv = kstrtoint(buf, 0, &value); + if (rv) + return rv; + if (value < 0 || value > 2) return -EINVAL; @@ -2181,7 +2295,6 @@ static int show_dsts(struct seq_file *m, void *data) u32 retval = -1; err = asus_wmi_get_devstate(asus, asus->debug.dev_id, &retval); - if (err < 0) return err; @@ -2198,7 +2311,6 @@ static int show_devs(struct seq_file *m, void *data) err = asus_wmi_set_devstate(asus->debug.dev_id, asus->debug.ctrl_param, &retval); - if (err < 0) return err; @@ -2334,7 +2446,6 @@ static int asus_wmi_add(struct platform_device *pdev) goto fail_input; err = asus_wmi_fan_init(asus); /* probably no problems on error */ - asus_hwmon_fan_set_auto(asus); err = asus_wmi_hwmon_init(asus); if (err) @@ -2392,6 +2503,8 @@ static int asus_wmi_add(struct platform_device *pdev) goto fail_wmi_handler; } + asus_wmi_battery_init(asus); + asus_wmi_debugfs_init(asus); return 0; @@ -2426,7 +2539,8 @@ static int asus_wmi_remove(struct platform_device *device) asus_wmi_rfkill_exit(asus); asus_wmi_debugfs_exit(asus); asus_wmi_sysfs_exit(asus->platform_device); - asus_hwmon_fan_set_auto(asus); + asus_fan_set_auto(asus); + asus_wmi_battery_exit(asus); kfree(asus); return 0; |