5116 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Asus PC WMI hotkey driver4 *5 * Copyright(C) 2010 Intel Corporation.6 * Copyright(C) 2010-2011 Corentin Chary <corentin.chary@gmail.com>7 *8 * Portions based on wistron_btns.c:9 * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz>10 * Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org>11 * Copyright (C) 2005 Dmitry Torokhov <dtor@mail.ru>12 */13 14#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt15 16#include <linux/acpi.h>17#include <linux/backlight.h>18#include <linux/debugfs.h>19#include <linux/delay.h>20#include <linux/dmi.h>21#include <linux/hwmon.h>22#include <linux/hwmon-sysfs.h>23#include <linux/init.h>24#include <linux/input.h>25#include <linux/input/sparse-keymap.h>26#include <linux/kernel.h>27#include <linux/leds.h>28#include <linux/minmax.h>29#include <linux/module.h>30#include <linux/pci.h>31#include <linux/pci_hotplug.h>32#include <linux/platform_data/x86/asus-wmi.h>33#include <linux/platform_device.h>34#include <linux/platform_profile.h>35#include <linux/power_supply.h>36#include <linux/rfkill.h>37#include <linux/seq_file.h>38#include <linux/slab.h>39#include <linux/types.h>40#include <linux/units.h>41 42#include <acpi/battery.h>43#include <acpi/video.h>44 45#include "asus-wmi.h"46 47MODULE_AUTHOR("Corentin Chary <corentin.chary@gmail.com>");48MODULE_AUTHOR("Yong Wang <yong.y.wang@intel.com>");49MODULE_DESCRIPTION("Asus Generic WMI Driver");50MODULE_LICENSE("GPL");51 52static bool fnlock_default = true;53module_param(fnlock_default, bool, 0444);54 55#define to_asus_wmi_driver(pdrv) \56 (container_of((pdrv), struct asus_wmi_driver, platform_driver))57 58#define ASUS_WMI_MGMT_GUID "97845ED0-4E6D-11DE-8A39-0800200C9A66"59 60#define NOTIFY_BRNUP_MIN 0x1161#define NOTIFY_BRNUP_MAX 0x1f62#define NOTIFY_BRNDOWN_MIN 0x2063#define NOTIFY_BRNDOWN_MAX 0x2e64#define NOTIFY_FNLOCK_TOGGLE 0x4e65#define NOTIFY_KBD_DOCK_CHANGE 0x7566#define NOTIFY_KBD_BRTUP 0xc467#define NOTIFY_KBD_BRTDWN 0xc568#define NOTIFY_KBD_BRTTOGGLE 0xc769#define NOTIFY_KBD_FBM 0x9970#define NOTIFY_KBD_TTP 0xae71#define NOTIFY_LID_FLIP 0xfa72#define NOTIFY_LID_FLIP_ROG 0xbd73 74#define ASUS_WMI_FNLOCK_BIOS_DISABLED BIT(0)75 76#define ASUS_MID_FAN_DESC "mid_fan"77#define ASUS_GPU_FAN_DESC "gpu_fan"78#define ASUS_FAN_DESC "cpu_fan"79#define ASUS_FAN_MFUN 0x1380#define ASUS_FAN_SFUN_READ 0x0681#define ASUS_FAN_SFUN_WRITE 0x0782 83/* Based on standard hwmon pwmX_enable values */84#define ASUS_FAN_CTRL_FULLSPEED 085#define ASUS_FAN_CTRL_MANUAL 186#define ASUS_FAN_CTRL_AUTO 287 88#define ASUS_FAN_BOOST_MODE_NORMAL 089#define ASUS_FAN_BOOST_MODE_OVERBOOST 190#define ASUS_FAN_BOOST_MODE_OVERBOOST_MASK 0x0191#define ASUS_FAN_BOOST_MODE_SILENT 292#define ASUS_FAN_BOOST_MODE_SILENT_MASK 0x0293#define ASUS_FAN_BOOST_MODES_MASK 0x0394 95#define ASUS_THROTTLE_THERMAL_POLICY_DEFAULT 096#define ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST 197#define ASUS_THROTTLE_THERMAL_POLICY_SILENT 298 99#define ASUS_THROTTLE_THERMAL_POLICY_DEFAULT_VIVO 0100#define ASUS_THROTTLE_THERMAL_POLICY_SILENT_VIVO 1101#define ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST_VIVO 2102 103#define PLATFORM_PROFILE_MAX 2104 105#define USB_INTEL_XUSB2PR 0xD0106#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI 0x9c31107 108#define ASUS_ACPI_UID_ASUSWMI "ASUSWMI"109 110#define WMI_EVENT_MASK 0xFFFF111 112#define FAN_CURVE_POINTS 8113#define FAN_CURVE_BUF_LEN 32114#define FAN_CURVE_DEV_CPU 0x00115#define FAN_CURVE_DEV_GPU 0x01116#define FAN_CURVE_DEV_MID 0x02117/* Mask to determine if setting temperature or percentage */118#define FAN_CURVE_PWM_MASK 0x04119 120/* Limits for tunables available on ASUS ROG laptops */121#define PPT_TOTAL_MIN 5122#define PPT_TOTAL_MAX 250123#define PPT_CPU_MIN 5124#define PPT_CPU_MAX 130125#define NVIDIA_BOOST_MIN 5126#define NVIDIA_BOOST_MAX 25127#define NVIDIA_TEMP_MIN 75128#define NVIDIA_TEMP_MAX 87129 130#define ASUS_SCREENPAD_BRIGHT_MIN 20131#define ASUS_SCREENPAD_BRIGHT_MAX 255132#define ASUS_SCREENPAD_BRIGHT_DEFAULT 60133 134#define ASUS_MINI_LED_MODE_MASK 0x03135/* Standard modes for devices with only on/off */136#define ASUS_MINI_LED_OFF 0x00137#define ASUS_MINI_LED_ON 0x01138/* New mode on some devices, define here to clarify remapping later */139#define ASUS_MINI_LED_STRONG_MODE 0x02140/* New modes for devices with 3 mini-led mode types */141#define ASUS_MINI_LED_2024_WEAK 0x00142#define ASUS_MINI_LED_2024_STRONG 0x01143#define ASUS_MINI_LED_2024_OFF 0x02144 145/* Controls the power state of the USB0 hub on ROG Ally which input is on */146#define ASUS_USB0_PWR_EC0_CSEE "\\_SB.PCI0.SBRG.EC0.CSEE"147/* 300ms so far seems to produce a reliable result on AC and battery */148#define ASUS_USB0_PWR_EC0_CSEE_WAIT 1500149 150static const char * const ashs_ids[] = { "ATK4001", "ATK4002", NULL };151 152static int throttle_thermal_policy_write(struct asus_wmi *);153 154static const struct dmi_system_id asus_ally_mcu_quirk[] = {155 {156 .matches = {157 DMI_MATCH(DMI_BOARD_NAME, "RC71L"),158 },159 },160 {161 .matches = {162 DMI_MATCH(DMI_BOARD_NAME, "RC72L"),163 },164 },165 { },166};167 168static bool ashs_present(void)169{170 int i = 0;171 while (ashs_ids[i]) {172 if (acpi_dev_found(ashs_ids[i++]))173 return true;174 }175 return false;176}177 178struct bios_args {179 u32 arg0;180 u32 arg1;181 u32 arg2; /* At least TUF Gaming series uses 3 dword input buffer. */182 u32 arg3;183 u32 arg4; /* Some ROG laptops require a full 5 input args */184 u32 arg5;185} __packed;186 187/*188 * Struct that's used for all methods called via AGFN. Naming is189 * identically to the AML code.190 */191struct agfn_args {192 u16 mfun; /* probably "Multi-function" to be called */193 u16 sfun; /* probably "Sub-function" to be called */194 u16 len; /* size of the hole struct, including subfunction fields */195 u8 stas; /* not used by now */196 u8 err; /* zero on success */197} __packed;198 199/* struct used for calling fan read and write methods */200struct agfn_fan_args {201 struct agfn_args agfn; /* common fields */202 u8 fan; /* fan number: 0: set auto mode 1: 1st fan */203 u32 speed; /* read: RPM/100 - write: 0-255 */204} __packed;205 206/*207 * <platform>/ - debugfs root directory208 * dev_id - current dev_id209 * ctrl_param - current ctrl_param210 * method_id - current method_id211 * devs - call DEVS(dev_id, ctrl_param) and print result212 * dsts - call DSTS(dev_id) and print result213 * call - call method_id(dev_id, ctrl_param) and print result214 */215struct asus_wmi_debug {216 struct dentry *root;217 u32 method_id;218 u32 dev_id;219 u32 ctrl_param;220};221 222struct asus_rfkill {223 struct asus_wmi *asus;224 struct rfkill *rfkill;225 u32 dev_id;226};227 228enum fan_type {229 FAN_TYPE_NONE = 0,230 FAN_TYPE_AGFN, /* deprecated on newer platforms */231 FAN_TYPE_SPEC83, /* starting in Spec 8.3, use CPU_FAN_CTRL */232};233 234struct fan_curve_data {235 bool enabled;236 u32 device_id;237 u8 temps[FAN_CURVE_POINTS];238 u8 percents[FAN_CURVE_POINTS];239};240 241struct asus_wmi {242 int dsts_id;243 int spec;244 int sfun;245 246 struct input_dev *inputdev;247 struct backlight_device *backlight_device;248 struct backlight_device *screenpad_backlight_device;249 struct platform_device *platform_device;250 251 struct led_classdev wlan_led;252 int wlan_led_wk;253 struct led_classdev tpd_led;254 int tpd_led_wk;255 struct led_classdev kbd_led;256 int kbd_led_wk;257 struct led_classdev lightbar_led;258 int lightbar_led_wk;259 struct led_classdev micmute_led;260 struct led_classdev camera_led;261 struct workqueue_struct *led_workqueue;262 struct work_struct tpd_led_work;263 struct work_struct wlan_led_work;264 struct work_struct lightbar_led_work;265 266 struct asus_rfkill wlan;267 struct asus_rfkill bluetooth;268 struct asus_rfkill wimax;269 struct asus_rfkill wwan3g;270 struct asus_rfkill gps;271 struct asus_rfkill uwb;272 273 int tablet_switch_event_code;274 u32 tablet_switch_dev_id;275 bool tablet_switch_inverted;276 277 /* The ROG Ally device requires the MCU USB device be disconnected before suspend */278 bool ally_mcu_usb_switch;279 280 enum fan_type fan_type;281 enum fan_type gpu_fan_type;282 enum fan_type mid_fan_type;283 int fan_pwm_mode;284 int gpu_fan_pwm_mode;285 int mid_fan_pwm_mode;286 int agfn_pwm;287 288 bool fan_boost_mode_available;289 u8 fan_boost_mode_mask;290 u8 fan_boost_mode;291 292 bool egpu_enable_available;293 bool dgpu_disable_available;294 u32 gpu_mux_dev;295 296 /* Tunables provided by ASUS for gaming laptops */297 u32 ppt_pl2_sppt;298 u32 ppt_pl1_spl;299 u32 ppt_apu_sppt;300 u32 ppt_platform_sppt;301 u32 ppt_fppt;302 u32 nv_dynamic_boost;303 u32 nv_temp_target;304 305 u32 kbd_rgb_dev;306 bool kbd_rgb_state_available;307 308 u8 throttle_thermal_policy_mode;309 u32 throttle_thermal_policy_dev;310 311 bool cpu_fan_curve_available;312 bool gpu_fan_curve_available;313 bool mid_fan_curve_available;314 struct fan_curve_data custom_fan_curves[3];315 316 struct platform_profile_handler platform_profile_handler;317 bool platform_profile_support;318 319 // The RSOC controls the maximum charging percentage.320 bool battery_rsoc_available;321 322 bool panel_overdrive_available;323 u32 mini_led_dev_id;324 325 struct hotplug_slot hotplug_slot;326 struct mutex hotplug_lock;327 struct mutex wmi_lock;328 struct workqueue_struct *hotplug_workqueue;329 struct work_struct hotplug_work;330 331 bool fnlock_locked;332 333 struct asus_wmi_debug debug;334 335 struct asus_wmi_driver *driver;336};337 338/* WMI ************************************************************************/339 340static int asus_wmi_evaluate_method3(u32 method_id,341 u32 arg0, u32 arg1, u32 arg2, u32 *retval)342{343 struct bios_args args = {344 .arg0 = arg0,345 .arg1 = arg1,346 .arg2 = arg2,347 };348 struct acpi_buffer input = { (acpi_size) sizeof(args), &args };349 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };350 acpi_status status;351 union acpi_object *obj;352 u32 tmp = 0;353 354 status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID, 0, method_id,355 &input, &output);356 357 pr_debug("%s called (0x%08x) with args: 0x%08x, 0x%08x, 0x%08x\n",358 __func__, method_id, arg0, arg1, arg2);359 if (ACPI_FAILURE(status)) {360 pr_debug("%s, (0x%08x), arg 0x%08x failed: %d\n",361 __func__, method_id, arg0, -EIO);362 return -EIO;363 }364 365 obj = (union acpi_object *)output.pointer;366 if (obj && obj->type == ACPI_TYPE_INTEGER)367 tmp = (u32) obj->integer.value;368 369 pr_debug("Result: 0x%08x\n", tmp);370 if (retval)371 *retval = tmp;372 373 kfree(obj);374 375 if (tmp == ASUS_WMI_UNSUPPORTED_METHOD) {376 pr_debug("%s, (0x%08x), arg 0x%08x failed: %d\n",377 __func__, method_id, arg0, -ENODEV);378 return -ENODEV;379 }380 381 return 0;382}383 384int asus_wmi_evaluate_method(u32 method_id, u32 arg0, u32 arg1, u32 *retval)385{386 return asus_wmi_evaluate_method3(method_id, arg0, arg1, 0, retval);387}388EXPORT_SYMBOL_GPL(asus_wmi_evaluate_method);389 390static int asus_wmi_evaluate_method5(u32 method_id,391 u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4, u32 *retval)392{393 struct bios_args args = {394 .arg0 = arg0,395 .arg1 = arg1,396 .arg2 = arg2,397 .arg3 = arg3,398 .arg4 = arg4,399 };400 struct acpi_buffer input = { (acpi_size) sizeof(args), &args };401 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };402 acpi_status status;403 union acpi_object *obj;404 u32 tmp = 0;405 406 status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID, 0, method_id,407 &input, &output);408 409 pr_debug("%s called (0x%08x) with args: 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",410 __func__, method_id, arg0, arg1, arg2, arg3, arg4);411 if (ACPI_FAILURE(status)) {412 pr_debug("%s, (0x%08x), arg 0x%08x failed: %d\n",413 __func__, method_id, arg0, -EIO);414 return -EIO;415 }416 417 obj = (union acpi_object *)output.pointer;418 if (obj && obj->type == ACPI_TYPE_INTEGER)419 tmp = (u32) obj->integer.value;420 421 pr_debug("Result: %x\n", tmp);422 if (retval)423 *retval = tmp;424 425 kfree(obj);426 427 if (tmp == ASUS_WMI_UNSUPPORTED_METHOD) {428 pr_debug("%s, (0x%08x), arg 0x%08x failed: %d\n",429 __func__, method_id, arg0, -ENODEV);430 return -ENODEV;431 }432 433 return 0;434}435 436/*437 * Returns as an error if the method output is not a buffer. Typically this438 * means that the method called is unsupported.439 */440static int asus_wmi_evaluate_method_buf(u32 method_id,441 u32 arg0, u32 arg1, u8 *ret_buffer, size_t size)442{443 struct bios_args args = {444 .arg0 = arg0,445 .arg1 = arg1,446 .arg2 = 0,447 };448 struct acpi_buffer input = { (acpi_size) sizeof(args), &args };449 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };450 acpi_status status;451 union acpi_object *obj;452 int err = 0;453 454 status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID, 0, method_id,455 &input, &output);456 457 pr_debug("%s called (0x%08x) with args: 0x%08x, 0x%08x\n",458 __func__, method_id, arg0, arg1);459 if (ACPI_FAILURE(status)) {460 pr_debug("%s, (0x%08x), arg 0x%08x failed: %d\n",461 __func__, method_id, arg0, -EIO);462 return -EIO;463 }464 465 obj = (union acpi_object *)output.pointer;466 467 switch (obj->type) {468 case ACPI_TYPE_BUFFER:469 if (obj->buffer.length > size) {470 err = -ENOSPC;471 break;472 }473 if (obj->buffer.length == 0) {474 err = -ENODATA;475 break;476 }477 478 memcpy(ret_buffer, obj->buffer.pointer, obj->buffer.length);479 break;480 case ACPI_TYPE_INTEGER:481 err = (u32)obj->integer.value;482 483 if (err == ASUS_WMI_UNSUPPORTED_METHOD)484 err = -ENODEV;485 /*486 * At least one method returns a 0 with no buffer if no arg487 * is provided, such as ASUS_WMI_DEVID_CPU_FAN_CURVE488 */489 if (err == 0)490 err = -ENODATA;491 break;492 default:493 err = -ENODATA;494 break;495 }496 497 kfree(obj);498 499 if (err) {500 pr_debug("%s, (0x%08x), arg 0x%08x failed: %d\n",501 __func__, method_id, arg0, err);502 return err;503 }504 505 return 0;506}507 508static int asus_wmi_evaluate_method_agfn(const struct acpi_buffer args)509{510 struct acpi_buffer input;511 u64 phys_addr;512 u32 retval;513 u32 status;514 515 /*516 * Copy to dma capable address otherwise memory corruption occurs as517 * bios has to be able to access it.518 */519 input.pointer = kmemdup(args.pointer, args.length, GFP_DMA | GFP_KERNEL);520 input.length = args.length;521 if (!input.pointer)522 return -ENOMEM;523 phys_addr = virt_to_phys(input.pointer);524 525 status = asus_wmi_evaluate_method(ASUS_WMI_METHODID_AGFN,526 phys_addr, 0, &retval);527 if (!status)528 memcpy(args.pointer, input.pointer, args.length);529 530 kfree(input.pointer);531 if (status)532 return -ENXIO;533 534 return retval;535}536 537static int asus_wmi_get_devstate(struct asus_wmi *asus, u32 dev_id, u32 *retval)538{539 int err;540 541 err = asus_wmi_evaluate_method(asus->dsts_id, dev_id, 0, retval);542 543 if (err)544 return err;545 546 if (*retval == ~0)547 return -ENODEV;548 549 return 0;550}551 552static int asus_wmi_set_devstate(u32 dev_id, u32 ctrl_param,553 u32 *retval)554{555 return asus_wmi_evaluate_method(ASUS_WMI_METHODID_DEVS, dev_id,556 ctrl_param, retval);557}558 559/* Helper for special devices with magic return codes */560static int asus_wmi_get_devstate_bits(struct asus_wmi *asus,561 u32 dev_id, u32 mask)562{563 u32 retval = 0;564 int err;565 566 err = asus_wmi_get_devstate(asus, dev_id, &retval);567 if (err < 0)568 return err;569 570 if (!(retval & ASUS_WMI_DSTS_PRESENCE_BIT))571 return -ENODEV;572 573 if (mask == ASUS_WMI_DSTS_STATUS_BIT) {574 if (retval & ASUS_WMI_DSTS_UNKNOWN_BIT)575 return -ENODEV;576 }577 578 return retval & mask;579}580 581static int asus_wmi_get_devstate_simple(struct asus_wmi *asus, u32 dev_id)582{583 return asus_wmi_get_devstate_bits(asus, dev_id,584 ASUS_WMI_DSTS_STATUS_BIT);585}586 587static bool asus_wmi_dev_is_present(struct asus_wmi *asus, u32 dev_id)588{589 u32 retval;590 int status = asus_wmi_get_devstate(asus, dev_id, &retval);591 pr_debug("%s called (0x%08x), retval: 0x%08x\n", __func__, dev_id, retval);592 593 return status == 0 && (retval & ASUS_WMI_DSTS_PRESENCE_BIT);594}595 596/* Input **********************************************************************/597static void asus_wmi_tablet_sw_report(struct asus_wmi *asus, bool value)598{599 input_report_switch(asus->inputdev, SW_TABLET_MODE,600 asus->tablet_switch_inverted ? !value : value);601 input_sync(asus->inputdev);602}603 604static void asus_wmi_tablet_sw_init(struct asus_wmi *asus, u32 dev_id, int event_code)605{606 struct device *dev = &asus->platform_device->dev;607 int result;608 609 result = asus_wmi_get_devstate_simple(asus, dev_id);610 if (result >= 0) {611 input_set_capability(asus->inputdev, EV_SW, SW_TABLET_MODE);612 asus_wmi_tablet_sw_report(asus, result);613 asus->tablet_switch_dev_id = dev_id;614 asus->tablet_switch_event_code = event_code;615 } else if (result == -ENODEV) {616 dev_err(dev, "This device has tablet-mode-switch quirk but got ENODEV checking it. This is a bug.");617 } else {618 dev_err(dev, "Error checking for tablet-mode-switch: %d\n", result);619 }620}621 622static int asus_wmi_input_init(struct asus_wmi *asus)623{624 struct device *dev = &asus->platform_device->dev;625 int err;626 627 asus->inputdev = input_allocate_device();628 if (!asus->inputdev)629 return -ENOMEM;630 631 asus->inputdev->name = asus->driver->input_name;632 asus->inputdev->phys = asus->driver->input_phys;633 asus->inputdev->id.bustype = BUS_HOST;634 asus->inputdev->dev.parent = dev;635 set_bit(EV_REP, asus->inputdev->evbit);636 637 err = sparse_keymap_setup(asus->inputdev, asus->driver->keymap, NULL);638 if (err)639 goto err_free_dev;640 641 switch (asus->driver->quirks->tablet_switch_mode) {642 case asus_wmi_no_tablet_switch:643 break;644 case asus_wmi_kbd_dock_devid:645 asus->tablet_switch_inverted = true;646 asus_wmi_tablet_sw_init(asus, ASUS_WMI_DEVID_KBD_DOCK, NOTIFY_KBD_DOCK_CHANGE);647 break;648 case asus_wmi_lid_flip_devid:649 asus_wmi_tablet_sw_init(asus, ASUS_WMI_DEVID_LID_FLIP, NOTIFY_LID_FLIP);650 break;651 case asus_wmi_lid_flip_rog_devid:652 asus_wmi_tablet_sw_init(asus, ASUS_WMI_DEVID_LID_FLIP_ROG, NOTIFY_LID_FLIP_ROG);653 break;654 }655 656 err = input_register_device(asus->inputdev);657 if (err)658 goto err_free_dev;659 660 return 0;661 662err_free_dev:663 input_free_device(asus->inputdev);664 return err;665}666 667static void asus_wmi_input_exit(struct asus_wmi *asus)668{669 if (asus->inputdev)670 input_unregister_device(asus->inputdev);671 672 asus->inputdev = NULL;673}674 675/* Tablet mode ****************************************************************/676 677static void asus_wmi_tablet_mode_get_state(struct asus_wmi *asus)678{679 int result;680 681 if (!asus->tablet_switch_dev_id)682 return;683 684 result = asus_wmi_get_devstate_simple(asus, asus->tablet_switch_dev_id);685 if (result >= 0)686 asus_wmi_tablet_sw_report(asus, result);687}688 689/* Charging mode, 1=Barrel, 2=USB ******************************************/690static ssize_t charge_mode_show(struct device *dev,691 struct device_attribute *attr, char *buf)692{693 struct asus_wmi *asus = dev_get_drvdata(dev);694 int result, value;695 696 result = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_CHARGE_MODE, &value);697 if (result < 0)698 return result;699 700 return sysfs_emit(buf, "%d\n", value & 0xff);701}702 703static DEVICE_ATTR_RO(charge_mode);704 705/* dGPU ********************************************************************/706static ssize_t dgpu_disable_show(struct device *dev,707 struct device_attribute *attr, char *buf)708{709 struct asus_wmi *asus = dev_get_drvdata(dev);710 int result;711 712 result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_DGPU);713 if (result < 0)714 return result;715 716 return sysfs_emit(buf, "%d\n", result);717}718 719/*720 * A user may be required to store the value twice, typcial store first, then721 * rescan PCI bus to activate power, then store a second time to save correctly.722 * The reason for this is that an extra code path in the ACPI is enabled when723 * the device and bus are powered.724 */725static ssize_t dgpu_disable_store(struct device *dev,726 struct device_attribute *attr,727 const char *buf, size_t count)728{729 int result, err;730 u32 disable;731 732 struct asus_wmi *asus = dev_get_drvdata(dev);733 734 result = kstrtou32(buf, 10, &disable);735 if (result)736 return result;737 738 if (disable > 1)739 return -EINVAL;740 741 if (asus->gpu_mux_dev) {742 result = asus_wmi_get_devstate_simple(asus, asus->gpu_mux_dev);743 if (result < 0)744 /* An error here may signal greater failure of GPU handling */745 return result;746 if (!result && disable) {747 err = -ENODEV;748 pr_warn("Can not disable dGPU when the MUX is in dGPU mode: %d\n", err);749 return err;750 }751 }752 753 err = asus_wmi_set_devstate(ASUS_WMI_DEVID_DGPU, disable, &result);754 if (err) {755 pr_warn("Failed to set dgpu disable: %d\n", err);756 return err;757 }758 759 if (result > 1) {760 pr_warn("Failed to set dgpu disable (result): 0x%x\n", result);761 return -EIO;762 }763 764 sysfs_notify(&asus->platform_device->dev.kobj, NULL, "dgpu_disable");765 766 return count;767}768static DEVICE_ATTR_RW(dgpu_disable);769 770/* eGPU ********************************************************************/771static ssize_t egpu_enable_show(struct device *dev,772 struct device_attribute *attr, char *buf)773{774 struct asus_wmi *asus = dev_get_drvdata(dev);775 int result;776 777 result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_EGPU);778 if (result < 0)779 return result;780 781 return sysfs_emit(buf, "%d\n", result);782}783 784/* The ACPI call to enable the eGPU also disables the internal dGPU */785static ssize_t egpu_enable_store(struct device *dev,786 struct device_attribute *attr,787 const char *buf, size_t count)788{789 int result, err;790 u32 enable;791 792 struct asus_wmi *asus = dev_get_drvdata(dev);793 794 err = kstrtou32(buf, 10, &enable);795 if (err)796 return err;797 798 if (enable > 1)799 return -EINVAL;800 801 err = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_EGPU_CONNECTED);802 if (err < 0) {803 pr_warn("Failed to get egpu connection status: %d\n", err);804 return err;805 }806 807 if (asus->gpu_mux_dev) {808 result = asus_wmi_get_devstate_simple(asus, asus->gpu_mux_dev);809 if (result < 0) {810 /* An error here may signal greater failure of GPU handling */811 pr_warn("Failed to get gpu mux status: %d\n", result);812 return result;813 }814 if (!result && enable) {815 err = -ENODEV;816 pr_warn("Can not enable eGPU when the MUX is in dGPU mode: %d\n", err);817 return err;818 }819 }820 821 err = asus_wmi_set_devstate(ASUS_WMI_DEVID_EGPU, enable, &result);822 if (err) {823 pr_warn("Failed to set egpu state: %d\n", err);824 return err;825 }826 827 if (result > 1) {828 pr_warn("Failed to set egpu state (retval): 0x%x\n", result);829 return -EIO;830 }831 832 sysfs_notify(&asus->platform_device->dev.kobj, NULL, "egpu_enable");833 834 return count;835}836static DEVICE_ATTR_RW(egpu_enable);837 838/* Is eGPU connected? *********************************************************/839static ssize_t egpu_connected_show(struct device *dev,840 struct device_attribute *attr, char *buf)841{842 struct asus_wmi *asus = dev_get_drvdata(dev);843 int result;844 845 result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_EGPU_CONNECTED);846 if (result < 0)847 return result;848 849 return sysfs_emit(buf, "%d\n", result);850}851 852static DEVICE_ATTR_RO(egpu_connected);853 854/* gpu mux switch *************************************************************/855static ssize_t gpu_mux_mode_show(struct device *dev,856 struct device_attribute *attr, char *buf)857{858 struct asus_wmi *asus = dev_get_drvdata(dev);859 int result;860 861 result = asus_wmi_get_devstate_simple(asus, asus->gpu_mux_dev);862 if (result < 0)863 return result;864 865 return sysfs_emit(buf, "%d\n", result);866}867 868static ssize_t gpu_mux_mode_store(struct device *dev,869 struct device_attribute *attr,870 const char *buf, size_t count)871{872 struct asus_wmi *asus = dev_get_drvdata(dev);873 int result, err;874 u32 optimus;875 876 err = kstrtou32(buf, 10, &optimus);877 if (err)878 return err;879 880 if (optimus > 1)881 return -EINVAL;882 883 if (asus->dgpu_disable_available) {884 result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_DGPU);885 if (result < 0)886 /* An error here may signal greater failure of GPU handling */887 return result;888 if (result && !optimus) {889 err = -ENODEV;890 pr_warn("Can not switch MUX to dGPU mode when dGPU is disabled: %d\n", err);891 return err;892 }893 }894 895 if (asus->egpu_enable_available) {896 result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_EGPU);897 if (result < 0)898 /* An error here may signal greater failure of GPU handling */899 return result;900 if (result && !optimus) {901 err = -ENODEV;902 pr_warn("Can not switch MUX to dGPU mode when eGPU is enabled: %d\n", err);903 return err;904 }905 }906 907 err = asus_wmi_set_devstate(asus->gpu_mux_dev, optimus, &result);908 if (err) {909 dev_err(dev, "Failed to set GPU MUX mode: %d\n", err);910 return err;911 }912 /* !1 is considered a fail by ASUS */913 if (result != 1) {914 dev_warn(dev, "Failed to set GPU MUX mode (result): 0x%x\n", result);915 return -EIO;916 }917 918 sysfs_notify(&asus->platform_device->dev.kobj, NULL, "gpu_mux_mode");919 920 return count;921}922static DEVICE_ATTR_RW(gpu_mux_mode);923 924/* TUF Laptop Keyboard RGB Modes **********************************************/925static ssize_t kbd_rgb_mode_store(struct device *dev,926 struct device_attribute *attr,927 const char *buf, size_t count)928{929 u32 cmd, mode, r, g, b, speed;930 struct led_classdev *led;931 struct asus_wmi *asus;932 int err;933 934 led = dev_get_drvdata(dev);935 asus = container_of(led, struct asus_wmi, kbd_led);936 937 if (sscanf(buf, "%d %d %d %d %d %d", &cmd, &mode, &r, &g, &b, &speed) != 6)938 return -EINVAL;939 940 /* B3 is set and B4 is save to BIOS */941 switch (cmd) {942 case 0:943 cmd = 0xb3;944 break;945 case 1:946 cmd = 0xb4;947 break;948 default:949 return -EINVAL;950 }951 952 /* These are the known usable modes across all TUF/ROG */953 if (mode >= 12 || mode == 9)954 mode = 10;955 956 switch (speed) {957 case 0:958 speed = 0xe1;959 break;960 case 1:961 speed = 0xeb;962 break;963 case 2:964 speed = 0xf5;965 break;966 default:967 speed = 0xeb;968 }969 970 err = asus_wmi_evaluate_method3(ASUS_WMI_METHODID_DEVS, asus->kbd_rgb_dev,971 cmd | (mode << 8) | (r << 16) | (g << 24), b | (speed << 8), NULL);972 if (err)973 return err;974 975 return count;976}977static DEVICE_ATTR_WO(kbd_rgb_mode);978 979static DEVICE_STRING_ATTR_RO(kbd_rgb_mode_index, 0444,980 "cmd mode red green blue speed");981 982static struct attribute *kbd_rgb_mode_attrs[] = {983 &dev_attr_kbd_rgb_mode.attr,984 &dev_attr_kbd_rgb_mode_index.attr.attr,985 NULL,986};987 988static const struct attribute_group kbd_rgb_mode_group = {989 .attrs = kbd_rgb_mode_attrs,990};991 992/* TUF Laptop Keyboard RGB State **********************************************/993static ssize_t kbd_rgb_state_store(struct device *dev,994 struct device_attribute *attr,995 const char *buf, size_t count)996{997 u32 flags, cmd, boot, awake, sleep, keyboard;998 int err;999 1000 if (sscanf(buf, "%d %d %d %d %d", &cmd, &boot, &awake, &sleep, &keyboard) != 5)1001 return -EINVAL;1002 1003 if (cmd)1004 cmd = BIT(2);1005 1006 flags = 0;1007 if (boot)1008 flags |= BIT(1);1009 if (awake)1010 flags |= BIT(3);1011 if (sleep)1012 flags |= BIT(5);1013 if (keyboard)1014 flags |= BIT(7);1015 1016 /* 0xbd is the required default arg0 for the method. Nothing happens otherwise */1017 err = asus_wmi_evaluate_method3(ASUS_WMI_METHODID_DEVS,1018 ASUS_WMI_DEVID_TUF_RGB_STATE, 0xbd | cmd << 8 | (flags << 16), 0, NULL);1019 if (err)1020 return err;1021 1022 return count;1023}1024static DEVICE_ATTR_WO(kbd_rgb_state);1025 1026static DEVICE_STRING_ATTR_RO(kbd_rgb_state_index, 0444,1027 "cmd boot awake sleep keyboard");1028 1029static struct attribute *kbd_rgb_state_attrs[] = {1030 &dev_attr_kbd_rgb_state.attr,1031 &dev_attr_kbd_rgb_state_index.attr.attr,1032 NULL,1033};1034 1035static const struct attribute_group kbd_rgb_state_group = {1036 .attrs = kbd_rgb_state_attrs,1037};1038 1039static const struct attribute_group *kbd_rgb_mode_groups[] = {1040 NULL,1041 NULL,1042 NULL,1043};1044 1045/* Tunable: PPT: Intel=PL1, AMD=SPPT *****************************************/1046static ssize_t ppt_pl2_sppt_store(struct device *dev,1047 struct device_attribute *attr,1048 const char *buf, size_t count)1049{1050 struct asus_wmi *asus = dev_get_drvdata(dev);1051 int result, err;1052 u32 value;1053 1054 result = kstrtou32(buf, 10, &value);1055 if (result)1056 return result;1057 1058 if (value < PPT_TOTAL_MIN || value > PPT_TOTAL_MAX)1059 return -EINVAL;1060 1061 err = asus_wmi_set_devstate(ASUS_WMI_DEVID_PPT_PL2_SPPT, value, &result);1062 if (err) {1063 pr_warn("Failed to set ppt_pl2_sppt: %d\n", err);1064 return err;1065 }1066 1067 if (result > 1) {1068 pr_warn("Failed to set ppt_pl2_sppt (result): 0x%x\n", result);1069 return -EIO;1070 }1071 1072 asus->ppt_pl2_sppt = value;1073 sysfs_notify(&asus->platform_device->dev.kobj, NULL, "ppt_pl2_sppt");1074 1075 return count;1076}1077 1078static ssize_t ppt_pl2_sppt_show(struct device *dev,1079 struct device_attribute *attr,1080 char *buf)1081{1082 struct asus_wmi *asus = dev_get_drvdata(dev);1083 1084 return sysfs_emit(buf, "%u\n", asus->ppt_pl2_sppt);1085}1086static DEVICE_ATTR_RW(ppt_pl2_sppt);1087 1088/* Tunable: PPT, Intel=PL1, AMD=SPL ******************************************/1089static ssize_t ppt_pl1_spl_store(struct device *dev,1090 struct device_attribute *attr,1091 const char *buf, size_t count)1092{1093 struct asus_wmi *asus = dev_get_drvdata(dev);1094 int result, err;1095 u32 value;1096 1097 result = kstrtou32(buf, 10, &value);1098 if (result)1099 return result;1100 1101 if (value < PPT_TOTAL_MIN || value > PPT_TOTAL_MAX)1102 return -EINVAL;1103 1104 err = asus_wmi_set_devstate(ASUS_WMI_DEVID_PPT_PL1_SPL, value, &result);1105 if (err) {1106 pr_warn("Failed to set ppt_pl1_spl: %d\n", err);1107 return err;1108 }1109 1110 if (result > 1) {1111 pr_warn("Failed to set ppt_pl1_spl (result): 0x%x\n", result);1112 return -EIO;1113 }1114 1115 asus->ppt_pl1_spl = value;1116 sysfs_notify(&asus->platform_device->dev.kobj, NULL, "ppt_pl1_spl");1117 1118 return count;1119}1120static ssize_t ppt_pl1_spl_show(struct device *dev,1121 struct device_attribute *attr,1122 char *buf)1123{1124 struct asus_wmi *asus = dev_get_drvdata(dev);1125 1126 return sysfs_emit(buf, "%u\n", asus->ppt_pl1_spl);1127}1128static DEVICE_ATTR_RW(ppt_pl1_spl);1129 1130/* Tunable: PPT APU FPPT ******************************************************/1131static ssize_t ppt_fppt_store(struct device *dev,1132 struct device_attribute *attr,1133 const char *buf, size_t count)1134{1135 struct asus_wmi *asus = dev_get_drvdata(dev);1136 int result, err;1137 u32 value;1138 1139 result = kstrtou32(buf, 10, &value);1140 if (result)1141 return result;1142 1143 if (value < PPT_TOTAL_MIN || value > PPT_TOTAL_MAX)1144 return -EINVAL;1145 1146 err = asus_wmi_set_devstate(ASUS_WMI_DEVID_PPT_FPPT, value, &result);1147 if (err) {1148 pr_warn("Failed to set ppt_fppt: %d\n", err);1149 return err;1150 }1151 1152 if (result > 1) {1153 pr_warn("Failed to set ppt_fppt (result): 0x%x\n", result);1154 return -EIO;1155 }1156 1157 asus->ppt_fppt = value;1158 sysfs_notify(&asus->platform_device->dev.kobj, NULL, "ppt_fpu_sppt");1159 1160 return count;1161}1162 1163static ssize_t ppt_fppt_show(struct device *dev,1164 struct device_attribute *attr,1165 char *buf)1166{1167 struct asus_wmi *asus = dev_get_drvdata(dev);1168 1169 return sysfs_emit(buf, "%u\n", asus->ppt_fppt);1170}1171static DEVICE_ATTR_RW(ppt_fppt);1172 1173/* Tunable: PPT APU SPPT *****************************************************/1174static ssize_t ppt_apu_sppt_store(struct device *dev,1175 struct device_attribute *attr,1176 const char *buf, size_t count)1177{1178 struct asus_wmi *asus = dev_get_drvdata(dev);1179 int result, err;1180 u32 value;1181 1182 result = kstrtou32(buf, 10, &value);1183 if (result)1184 return result;1185 1186 if (value < PPT_CPU_MIN || value > PPT_CPU_MAX)1187 return -EINVAL;1188 1189 err = asus_wmi_set_devstate(ASUS_WMI_DEVID_PPT_APU_SPPT, value, &result);1190 if (err) {1191 pr_warn("Failed to set ppt_apu_sppt: %d\n", err);1192 return err;1193 }1194 1195 if (result > 1) {1196 pr_warn("Failed to set ppt_apu_sppt (result): 0x%x\n", result);1197 return -EIO;1198 }1199 1200 asus->ppt_apu_sppt = value;1201 sysfs_notify(&asus->platform_device->dev.kobj, NULL, "ppt_apu_sppt");1202 1203 return count;1204}1205 1206static ssize_t ppt_apu_sppt_show(struct device *dev,1207 struct device_attribute *attr,1208 char *buf)1209{1210 struct asus_wmi *asus = dev_get_drvdata(dev);1211 1212 return sysfs_emit(buf, "%u\n", asus->ppt_apu_sppt);1213}1214static DEVICE_ATTR_RW(ppt_apu_sppt);1215 1216/* Tunable: PPT platform SPPT ************************************************/1217static ssize_t ppt_platform_sppt_store(struct device *dev,1218 struct device_attribute *attr,1219 const char *buf, size_t count)1220{1221 struct asus_wmi *asus = dev_get_drvdata(dev);1222 int result, err;1223 u32 value;1224 1225 result = kstrtou32(buf, 10, &value);1226 if (result)1227 return result;1228 1229 if (value < PPT_CPU_MIN || value > PPT_CPU_MAX)1230 return -EINVAL;1231 1232 err = asus_wmi_set_devstate(ASUS_WMI_DEVID_PPT_PLAT_SPPT, value, &result);1233 if (err) {1234 pr_warn("Failed to set ppt_platform_sppt: %d\n", err);1235 return err;1236 }1237 1238 if (result > 1) {1239 pr_warn("Failed to set ppt_platform_sppt (result): 0x%x\n", result);1240 return -EIO;1241 }1242 1243 asus->ppt_platform_sppt = value;1244 sysfs_notify(&asus->platform_device->dev.kobj, NULL, "ppt_platform_sppt");1245 1246 return count;1247}1248 1249static ssize_t ppt_platform_sppt_show(struct device *dev,1250 struct device_attribute *attr,1251 char *buf)1252{1253 struct asus_wmi *asus = dev_get_drvdata(dev);1254 1255 return sysfs_emit(buf, "%u\n", asus->ppt_platform_sppt);1256}1257static DEVICE_ATTR_RW(ppt_platform_sppt);1258 1259/* Tunable: NVIDIA dynamic boost *********************************************/1260static ssize_t nv_dynamic_boost_store(struct device *dev,1261 struct device_attribute *attr,1262 const char *buf, size_t count)1263{1264 struct asus_wmi *asus = dev_get_drvdata(dev);1265 int result, err;1266 u32 value;1267 1268 result = kstrtou32(buf, 10, &value);1269 if (result)1270 return result;1271 1272 if (value < NVIDIA_BOOST_MIN || value > NVIDIA_BOOST_MAX)1273 return -EINVAL;1274 1275 err = asus_wmi_set_devstate(ASUS_WMI_DEVID_NV_DYN_BOOST, value, &result);1276 if (err) {1277 pr_warn("Failed to set nv_dynamic_boost: %d\n", err);1278 return err;1279 }1280 1281 if (result > 1) {1282 pr_warn("Failed to set nv_dynamic_boost (result): 0x%x\n", result);1283 return -EIO;1284 }1285 1286 asus->nv_dynamic_boost = value;1287 sysfs_notify(&asus->platform_device->dev.kobj, NULL, "nv_dynamic_boost");1288 1289 return count;1290}1291 1292static ssize_t nv_dynamic_boost_show(struct device *dev,1293 struct device_attribute *attr,1294 char *buf)1295{1296 struct asus_wmi *asus = dev_get_drvdata(dev);1297 1298 return sysfs_emit(buf, "%u\n", asus->nv_dynamic_boost);1299}1300static DEVICE_ATTR_RW(nv_dynamic_boost);1301 1302/* Tunable: NVIDIA temperature target ****************************************/1303static ssize_t nv_temp_target_store(struct device *dev,1304 struct device_attribute *attr,1305 const char *buf, size_t count)1306{1307 struct asus_wmi *asus = dev_get_drvdata(dev);1308 int result, err;1309 u32 value;1310 1311 result = kstrtou32(buf, 10, &value);1312 if (result)1313 return result;1314 1315 if (value < NVIDIA_TEMP_MIN || value > NVIDIA_TEMP_MAX)1316 return -EINVAL;1317 1318 err = asus_wmi_set_devstate(ASUS_WMI_DEVID_NV_THERM_TARGET, value, &result);1319 if (err) {1320 pr_warn("Failed to set nv_temp_target: %d\n", err);1321 return err;1322 }1323 1324 if (result > 1) {1325 pr_warn("Failed to set nv_temp_target (result): 0x%x\n", result);1326 return -EIO;1327 }1328 1329 asus->nv_temp_target = value;1330 sysfs_notify(&asus->platform_device->dev.kobj, NULL, "nv_temp_target");1331 1332 return count;1333}1334 1335static ssize_t nv_temp_target_show(struct device *dev,1336 struct device_attribute *attr,1337 char *buf)1338{1339 struct asus_wmi *asus = dev_get_drvdata(dev);1340 1341 return sysfs_emit(buf, "%u\n", asus->nv_temp_target);1342}1343static DEVICE_ATTR_RW(nv_temp_target);1344 1345/* Ally MCU Powersave ********************************************************/1346static ssize_t mcu_powersave_show(struct device *dev,1347 struct device_attribute *attr, char *buf)1348{1349 struct asus_wmi *asus = dev_get_drvdata(dev);1350 int result;1351 1352 result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_MCU_POWERSAVE);1353 if (result < 0)1354 return result;1355 1356 return sysfs_emit(buf, "%d\n", result);1357}1358 1359static ssize_t mcu_powersave_store(struct device *dev,1360 struct device_attribute *attr,1361 const char *buf, size_t count)1362{1363 int result, err;1364 u32 enable;1365 1366 struct asus_wmi *asus = dev_get_drvdata(dev);1367 1368 result = kstrtou32(buf, 10, &enable);1369 if (result)1370 return result;1371 1372 if (enable > 1)1373 return -EINVAL;1374 1375 err = asus_wmi_set_devstate(ASUS_WMI_DEVID_MCU_POWERSAVE, enable, &result);1376 if (err) {1377 pr_warn("Failed to set MCU powersave: %d\n", err);1378 return err;1379 }1380 1381 if (result > 1) {1382 pr_warn("Failed to set MCU powersave (result): 0x%x\n", result);1383 return -EIO;1384 }1385 1386 sysfs_notify(&asus->platform_device->dev.kobj, NULL, "mcu_powersave");1387 1388 return count;1389}1390static DEVICE_ATTR_RW(mcu_powersave);1391 1392/* Battery ********************************************************************/1393 1394/* The battery maximum charging percentage */1395static int charge_end_threshold;1396 1397static ssize_t charge_control_end_threshold_store(struct device *dev,1398 struct device_attribute *attr,1399 const char *buf, size_t count)1400{1401 int value, ret, rv;1402 1403 ret = kstrtouint(buf, 10, &value);1404 if (ret)1405 return ret;1406 1407 if (value < 0 || value > 100)1408 return -EINVAL;1409 1410 ret = asus_wmi_set_devstate(ASUS_WMI_DEVID_RSOC, value, &rv);1411 if (ret)1412 return ret;1413 1414 if (rv != 1)1415 return -EIO;1416 1417 /* There isn't any method in the DSDT to read the threshold, so we1418 * save the threshold.1419 */1420 charge_end_threshold = value;1421 return count;1422}1423 1424static ssize_t charge_control_end_threshold_show(struct device *device,1425 struct device_attribute *attr,1426 char *buf)1427{1428 return sysfs_emit(buf, "%d\n", charge_end_threshold);1429}1430 1431static DEVICE_ATTR_RW(charge_control_end_threshold);1432 1433static int asus_wmi_battery_add(struct power_supply *battery, struct acpi_battery_hook *hook)1434{1435 /* The WMI method does not provide a way to specific a battery, so we1436 * just assume it is the first battery.1437 * Note: On some newer ASUS laptops (Zenbook UM431DA), the primary/first1438 * battery is named BATT.1439 */1440 if (strcmp(battery->desc->name, "BAT0") != 0 &&1441 strcmp(battery->desc->name, "BAT1") != 0 &&1442 strcmp(battery->desc->name, "BATC") != 0 &&1443 strcmp(battery->desc->name, "BATT") != 0)1444 return -ENODEV;1445 1446 if (device_create_file(&battery->dev,1447 &dev_attr_charge_control_end_threshold))1448 return -ENODEV;1449 1450 /* The charge threshold is only reset when the system is power cycled,1451 * and we can't get the current threshold so let set it to 100% when1452 * a battery is added.1453 */1454 asus_wmi_set_devstate(ASUS_WMI_DEVID_RSOC, 100, NULL);1455 charge_end_threshold = 100;1456 1457 return 0;1458}1459 1460static int asus_wmi_battery_remove(struct power_supply *battery, struct acpi_battery_hook *hook)1461{1462 device_remove_file(&battery->dev,1463 &dev_attr_charge_control_end_threshold);1464 return 0;1465}1466 1467static struct acpi_battery_hook battery_hook = {1468 .add_battery = asus_wmi_battery_add,1469 .remove_battery = asus_wmi_battery_remove,1470 .name = "ASUS Battery Extension",1471};1472 1473static void asus_wmi_battery_init(struct asus_wmi *asus)1474{1475 asus->battery_rsoc_available = false;1476 if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_RSOC)) {1477 asus->battery_rsoc_available = true;1478 battery_hook_register(&battery_hook);1479 }1480}1481 1482static void asus_wmi_battery_exit(struct asus_wmi *asus)1483{1484 if (asus->battery_rsoc_available)1485 battery_hook_unregister(&battery_hook);1486}1487 1488/* LEDs ***********************************************************************/1489 1490/*1491 * These functions actually update the LED's, and are called from a1492 * workqueue. By doing this as separate work rather than when the LED1493 * subsystem asks, we avoid messing with the Asus ACPI stuff during a1494 * potentially bad time, such as a timer interrupt.1495 */1496static void tpd_led_update(struct work_struct *work)1497{1498 int ctrl_param;1499 struct asus_wmi *asus;1500 1501 asus = container_of(work, struct asus_wmi, tpd_led_work);1502 1503 ctrl_param = asus->tpd_led_wk;1504 asus_wmi_set_devstate(ASUS_WMI_DEVID_TOUCHPAD_LED, ctrl_param, NULL);1505}1506 1507static void tpd_led_set(struct led_classdev *led_cdev,1508 enum led_brightness value)1509{1510 struct asus_wmi *asus;1511 1512 asus = container_of(led_cdev, struct asus_wmi, tpd_led);1513 1514 asus->tpd_led_wk = !!value;1515 queue_work(asus->led_workqueue, &asus->tpd_led_work);1516}1517 1518static int read_tpd_led_state(struct asus_wmi *asus)1519{1520 return asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_TOUCHPAD_LED);1521}1522 1523static enum led_brightness tpd_led_get(struct led_classdev *led_cdev)1524{1525 struct asus_wmi *asus;1526 1527 asus = container_of(led_cdev, struct asus_wmi, tpd_led);1528 1529 return read_tpd_led_state(asus);1530}1531 1532static void kbd_led_update(struct asus_wmi *asus)1533{1534 int ctrl_param = 0;1535 1536 ctrl_param = 0x80 | (asus->kbd_led_wk & 0x7F);1537 asus_wmi_set_devstate(ASUS_WMI_DEVID_KBD_BACKLIGHT, ctrl_param, NULL);1538}1539 1540static int kbd_led_read(struct asus_wmi *asus, int *level, int *env)1541{1542 int retval;1543 1544 /*1545 * bits 0-2: level1546 * bit 7: light on/off1547 * bit 8-10: environment (0: dark, 1: normal, 2: light)1548 * bit 17: status unknown1549 */1550 retval = asus_wmi_get_devstate_bits(asus, ASUS_WMI_DEVID_KBD_BACKLIGHT,1551 0xFFFF);1552 1553 /* Unknown status is considered as off */1554 if (retval == 0x8000)1555 retval = 0;1556 1557 if (retval < 0)1558 return retval;1559 1560 if (level)1561 *level = retval & 0x7F;1562 if (env)1563 *env = (retval >> 8) & 0x7F;1564 return 0;1565}1566 1567static void do_kbd_led_set(struct led_classdev *led_cdev, int value)1568{1569 struct asus_wmi *asus;1570 int max_level;1571 1572 asus = container_of(led_cdev, struct asus_wmi, kbd_led);1573 max_level = asus->kbd_led.max_brightness;1574 1575 asus->kbd_led_wk = clamp_val(value, 0, max_level);1576 kbd_led_update(asus);1577}1578 1579static void kbd_led_set(struct led_classdev *led_cdev,1580 enum led_brightness value)1581{1582 /* Prevent disabling keyboard backlight on module unregister */1583 if (led_cdev->flags & LED_UNREGISTERING)1584 return;1585 1586 do_kbd_led_set(led_cdev, value);1587}1588 1589static void kbd_led_set_by_kbd(struct asus_wmi *asus, enum led_brightness value)1590{1591 struct led_classdev *led_cdev = &asus->kbd_led;1592 1593 do_kbd_led_set(led_cdev, value);1594 led_classdev_notify_brightness_hw_changed(led_cdev, asus->kbd_led_wk);1595}1596 1597static enum led_brightness kbd_led_get(struct led_classdev *led_cdev)1598{1599 struct asus_wmi *asus;1600 int retval, value;1601 1602 asus = container_of(led_cdev, struct asus_wmi, kbd_led);1603 1604 retval = kbd_led_read(asus, &value, NULL);1605 if (retval < 0)1606 return retval;1607 1608 return value;1609}1610 1611static int wlan_led_unknown_state(struct asus_wmi *asus)1612{1613 u32 result;1614 1615 asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WIRELESS_LED, &result);1616 1617 return result & ASUS_WMI_DSTS_UNKNOWN_BIT;1618}1619 1620static void wlan_led_update(struct work_struct *work)1621{1622 int ctrl_param;1623 struct asus_wmi *asus;1624 1625 asus = container_of(work, struct asus_wmi, wlan_led_work);1626 1627 ctrl_param = asus->wlan_led_wk;1628 asus_wmi_set_devstate(ASUS_WMI_DEVID_WIRELESS_LED, ctrl_param, NULL);1629}1630 1631static void wlan_led_set(struct led_classdev *led_cdev,1632 enum led_brightness value)1633{1634 struct asus_wmi *asus;1635 1636 asus = container_of(led_cdev, struct asus_wmi, wlan_led);1637 1638 asus->wlan_led_wk = !!value;1639 queue_work(asus->led_workqueue, &asus->wlan_led_work);1640}1641 1642static enum led_brightness wlan_led_get(struct led_classdev *led_cdev)1643{1644 struct asus_wmi *asus;1645 u32 result;1646 1647 asus = container_of(led_cdev, struct asus_wmi, wlan_led);1648 asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WIRELESS_LED, &result);1649 1650 return result & ASUS_WMI_DSTS_BRIGHTNESS_MASK;1651}1652 1653static void lightbar_led_update(struct work_struct *work)1654{1655 struct asus_wmi *asus;1656 int ctrl_param;1657 1658 asus = container_of(work, struct asus_wmi, lightbar_led_work);1659 1660 ctrl_param = asus->lightbar_led_wk;1661 asus_wmi_set_devstate(ASUS_WMI_DEVID_LIGHTBAR, ctrl_param, NULL);1662}1663 1664static void lightbar_led_set(struct led_classdev *led_cdev,1665 enum led_brightness value)1666{1667 struct asus_wmi *asus;1668 1669 asus = container_of(led_cdev, struct asus_wmi, lightbar_led);1670 1671 asus->lightbar_led_wk = !!value;1672 queue_work(asus->led_workqueue, &asus->lightbar_led_work);1673}1674 1675static enum led_brightness lightbar_led_get(struct led_classdev *led_cdev)1676{1677 struct asus_wmi *asus;1678 u32 result;1679 1680 asus = container_of(led_cdev, struct asus_wmi, lightbar_led);1681 asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_LIGHTBAR, &result);1682 1683 return result & ASUS_WMI_DSTS_LIGHTBAR_MASK;1684}1685 1686static int micmute_led_set(struct led_classdev *led_cdev,1687 enum led_brightness brightness)1688{1689 int state = brightness != LED_OFF;1690 int err;1691 1692 err = asus_wmi_set_devstate(ASUS_WMI_DEVID_MICMUTE_LED, state, NULL);1693 return err < 0 ? err : 0;1694}1695 1696static enum led_brightness camera_led_get(struct led_classdev *led_cdev)1697{1698 struct asus_wmi *asus;1699 u32 result;1700 1701 asus = container_of(led_cdev, struct asus_wmi, camera_led);1702 asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_CAMERA_LED, &result);1703 1704 return result & ASUS_WMI_DSTS_BRIGHTNESS_MASK;1705}1706 1707static int camera_led_set(struct led_classdev *led_cdev,1708 enum led_brightness brightness)1709{1710 int state = brightness != LED_OFF;1711 int err;1712 1713 err = asus_wmi_set_devstate(ASUS_WMI_DEVID_CAMERA_LED, state, NULL);1714 return err < 0 ? err : 0;1715}1716 1717static void asus_wmi_led_exit(struct asus_wmi *asus)1718{1719 led_classdev_unregister(&asus->kbd_led);1720 led_classdev_unregister(&asus->tpd_led);1721 led_classdev_unregister(&asus->wlan_led);1722 led_classdev_unregister(&asus->lightbar_led);1723 led_classdev_unregister(&asus->micmute_led);1724 led_classdev_unregister(&asus->camera_led);1725 1726 if (asus->led_workqueue)1727 destroy_workqueue(asus->led_workqueue);1728}1729 1730static int asus_wmi_led_init(struct asus_wmi *asus)1731{1732 int rv = 0, num_rgb_groups = 0, led_val;1733 1734 if (asus->kbd_rgb_dev)1735 kbd_rgb_mode_groups[num_rgb_groups++] = &kbd_rgb_mode_group;1736 if (asus->kbd_rgb_state_available)1737 kbd_rgb_mode_groups[num_rgb_groups++] = &kbd_rgb_state_group;1738 1739 asus->led_workqueue = create_singlethread_workqueue("led_workqueue");1740 if (!asus->led_workqueue)1741 return -ENOMEM;1742 1743 if (read_tpd_led_state(asus) >= 0) {1744 INIT_WORK(&asus->tpd_led_work, tpd_led_update);1745 1746 asus->tpd_led.name = "asus::touchpad";1747 asus->tpd_led.brightness_set = tpd_led_set;1748 asus->tpd_led.brightness_get = tpd_led_get;1749 asus->tpd_led.max_brightness = 1;1750 1751 rv = led_classdev_register(&asus->platform_device->dev,1752 &asus->tpd_led);1753 if (rv)1754 goto error;1755 }1756 1757 if (!kbd_led_read(asus, &led_val, NULL) && !dmi_check_system(asus_use_hid_led_dmi_ids)) {1758 pr_info("using asus-wmi for asus::kbd_backlight\n");1759 asus->kbd_led_wk = led_val;1760 asus->kbd_led.name = "asus::kbd_backlight";1761 asus->kbd_led.flags = LED_BRIGHT_HW_CHANGED;1762 asus->kbd_led.brightness_set = kbd_led_set;1763 asus->kbd_led.brightness_get = kbd_led_get;1764 asus->kbd_led.max_brightness = 3;1765 1766 if (num_rgb_groups != 0)1767 asus->kbd_led.groups = kbd_rgb_mode_groups;1768 1769 rv = led_classdev_register(&asus->platform_device->dev,1770 &asus->kbd_led);1771 if (rv)1772 goto error;1773 }1774 1775 if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_WIRELESS_LED)1776 && (asus->driver->quirks->wapf > 0)) {1777 INIT_WORK(&asus->wlan_led_work, wlan_led_update);1778 1779 asus->wlan_led.name = "asus::wlan";1780 asus->wlan_led.brightness_set = wlan_led_set;1781 if (!wlan_led_unknown_state(asus))1782 asus->wlan_led.brightness_get = wlan_led_get;1783 asus->wlan_led.flags = LED_CORE_SUSPENDRESUME;1784 asus->wlan_led.max_brightness = 1;1785 asus->wlan_led.default_trigger = "asus-wlan";1786 1787 rv = led_classdev_register(&asus->platform_device->dev,1788 &asus->wlan_led);1789 if (rv)1790 goto error;1791 }1792 1793 if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_LIGHTBAR)) {1794 INIT_WORK(&asus->lightbar_led_work, lightbar_led_update);1795 1796 asus->lightbar_led.name = "asus::lightbar";1797 asus->lightbar_led.brightness_set = lightbar_led_set;1798 asus->lightbar_led.brightness_get = lightbar_led_get;1799 asus->lightbar_led.max_brightness = 1;1800 1801 rv = led_classdev_register(&asus->platform_device->dev,1802 &asus->lightbar_led);1803 }1804 1805 if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_MICMUTE_LED)) {1806 asus->micmute_led.name = "platform::micmute";1807 asus->micmute_led.max_brightness = 1;1808 asus->micmute_led.brightness_set_blocking = micmute_led_set;1809 asus->micmute_led.default_trigger = "audio-micmute";1810 1811 rv = led_classdev_register(&asus->platform_device->dev,1812 &asus->micmute_led);1813 if (rv)1814 goto error;1815 }1816 1817 if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_CAMERA_LED)) {1818 asus->camera_led.name = "asus::camera";1819 asus->camera_led.max_brightness = 1;1820 asus->camera_led.brightness_get = camera_led_get;1821 asus->camera_led.brightness_set_blocking = camera_led_set;1822 1823 rv = led_classdev_register(&asus->platform_device->dev,1824 &asus->camera_led);1825 if (rv)1826 goto error;1827 }1828 1829 if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_OOBE)) {1830 /*1831 * Disable OOBE state, so that e.g. the keyboard backlight1832 * works.1833 */1834 rv = asus_wmi_set_devstate(ASUS_WMI_DEVID_OOBE, 1, NULL);1835 if (rv)1836 goto error;1837 }1838 1839error:1840 if (rv)1841 asus_wmi_led_exit(asus);1842 1843 return rv;1844}1845 1846/* RF *************************************************************************/1847 1848/*1849 * PCI hotplug (for wlan rfkill)1850 */1851static bool asus_wlan_rfkill_blocked(struct asus_wmi *asus)1852{1853 int result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WLAN);1854 1855 if (result < 0)1856 return false;1857 return !result;1858}1859 1860static void asus_rfkill_hotplug(struct asus_wmi *asus)1861{1862 struct pci_dev *dev;1863 struct pci_bus *bus;1864 bool blocked;1865 bool absent;1866 u32 l;1867 1868 mutex_lock(&asus->wmi_lock);1869 blocked = asus_wlan_rfkill_blocked(asus);1870 mutex_unlock(&asus->wmi_lock);1871 1872 mutex_lock(&asus->hotplug_lock);1873 pci_lock_rescan_remove();1874 1875 if (asus->wlan.rfkill)1876 rfkill_set_sw_state(asus->wlan.rfkill, blocked);1877 1878 if (asus->hotplug_slot.ops) {1879 bus = pci_find_bus(0, 1);1880 if (!bus) {1881 pr_warn("Unable to find PCI bus 1?\n");1882 goto out_unlock;1883 }1884 1885 if (pci_bus_read_config_dword(bus, 0, PCI_VENDOR_ID, &l)) {1886 pr_err("Unable to read PCI config space?\n");1887 goto out_unlock;1888 }1889 absent = (l == 0xffffffff);1890 1891 if (blocked != absent) {1892 pr_warn("BIOS says wireless lan is %s, but the pci device is %s\n",1893 blocked ? "blocked" : "unblocked",1894 absent ? "absent" : "present");1895 pr_warn("skipped wireless hotplug as probably inappropriate for this model\n");1896 goto out_unlock;1897 }1898 1899 if (!blocked) {1900 dev = pci_get_slot(bus, 0);1901 if (dev) {1902 /* Device already present */1903 pci_dev_put(dev);1904 goto out_unlock;1905 }1906 dev = pci_scan_single_device(bus, 0);1907 if (dev) {1908 pci_bus_assign_resources(bus);1909 pci_bus_add_device(dev);1910 }1911 } else {1912 dev = pci_get_slot(bus, 0);1913 if (dev) {1914 pci_stop_and_remove_bus_device(dev);1915 pci_dev_put(dev);1916 }1917 }1918 }1919 1920out_unlock:1921 pci_unlock_rescan_remove();1922 mutex_unlock(&asus->hotplug_lock);1923}1924 1925static void asus_rfkill_notify(acpi_handle handle, u32 event, void *data)1926{1927 struct asus_wmi *asus = data;1928 1929 if (event != ACPI_NOTIFY_BUS_CHECK)1930 return;1931 1932 /*1933 * We can't call directly asus_rfkill_hotplug because most1934 * of the time WMBC is still being executed and not reetrant.1935 * There is currently no way to tell ACPICA that we want this1936 * method to be serialized, we schedule a asus_rfkill_hotplug1937 * call later, in a safer context.1938 */1939 queue_work(asus->hotplug_workqueue, &asus->hotplug_work);1940}1941 1942static int asus_register_rfkill_notifier(struct asus_wmi *asus, char *node)1943{1944 acpi_status status;1945 acpi_handle handle;1946 1947 status = acpi_get_handle(NULL, node, &handle);1948 if (ACPI_FAILURE(status))1949 return -ENODEV;1950 1951 status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,1952 asus_rfkill_notify, asus);1953 if (ACPI_FAILURE(status))1954 pr_warn("Failed to register notify on %s\n", node);1955 1956 return 0;1957}1958 1959static void asus_unregister_rfkill_notifier(struct asus_wmi *asus, char *node)1960{1961 acpi_status status = AE_OK;1962 acpi_handle handle;1963 1964 status = acpi_get_handle(NULL, node, &handle);1965 if (ACPI_FAILURE(status))1966 return;1967 1968 status = acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,1969 asus_rfkill_notify);1970 if (ACPI_FAILURE(status))1971 pr_err("Error removing rfkill notify handler %s\n", node);1972}1973 1974static int asus_get_adapter_status(struct hotplug_slot *hotplug_slot,1975 u8 *value)1976{1977 struct asus_wmi *asus = container_of(hotplug_slot,1978 struct asus_wmi, hotplug_slot);1979 int result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WLAN);1980 1981 if (result < 0)1982 return result;1983 1984 *value = !!result;1985 return 0;1986}1987 1988static const struct hotplug_slot_ops asus_hotplug_slot_ops = {1989 .get_adapter_status = asus_get_adapter_status,1990 .get_power_status = asus_get_adapter_status,1991};1992 1993static void asus_hotplug_work(struct work_struct *work)1994{1995 struct asus_wmi *asus;1996 1997 asus = container_of(work, struct asus_wmi, hotplug_work);1998 asus_rfkill_hotplug(asus);1999}2000 2001static int asus_setup_pci_hotplug(struct asus_wmi *asus)2002{2003 int ret = -ENOMEM;2004 struct pci_bus *bus = pci_find_bus(0, 1);2005 2006 if (!bus) {2007 pr_err("Unable to find wifi PCI bus\n");2008 return -ENODEV;2009 }2010 2011 asus->hotplug_workqueue =2012 create_singlethread_workqueue("hotplug_workqueue");2013 if (!asus->hotplug_workqueue)2014 goto error_workqueue;2015 2016 INIT_WORK(&asus->hotplug_work, asus_hotplug_work);2017 2018 asus->hotplug_slot.ops = &asus_hotplug_slot_ops;2019 2020 ret = pci_hp_register(&asus->hotplug_slot, bus, 0, "asus-wifi");2021 if (ret) {2022 pr_err("Unable to register hotplug slot - %d\n", ret);2023 goto error_register;2024 }2025 2026 return 0;2027 2028error_register:2029 asus->hotplug_slot.ops = NULL;2030 destroy_workqueue(asus->hotplug_workqueue);2031error_workqueue:2032 return ret;2033}2034 2035/*2036 * Rfkill devices2037 */2038static int asus_rfkill_set(void *data, bool blocked)2039{2040 struct asus_rfkill *priv = data;2041 u32 ctrl_param = !blocked;2042 u32 dev_id = priv->dev_id;2043 2044 /*2045 * If the user bit is set, BIOS can't set and record the wlan status,2046 * it will report the value read from id ASUS_WMI_DEVID_WLAN_LED2047 * while we query the wlan status through WMI(ASUS_WMI_DEVID_WLAN).2048 * So, we have to record wlan status in id ASUS_WMI_DEVID_WLAN_LED2049 * while setting the wlan status through WMI.2050 * This is also the behavior that windows app will do.2051 */2052 if ((dev_id == ASUS_WMI_DEVID_WLAN) &&2053 priv->asus->driver->wlan_ctrl_by_user)2054 dev_id = ASUS_WMI_DEVID_WLAN_LED;2055 2056 return asus_wmi_set_devstate(dev_id, ctrl_param, NULL);2057}2058 2059static void asus_rfkill_query(struct rfkill *rfkill, void *data)2060{2061 struct asus_rfkill *priv = data;2062 int result;2063 2064 result = asus_wmi_get_devstate_simple(priv->asus, priv->dev_id);2065 2066 if (result < 0)2067 return;2068 2069 rfkill_set_sw_state(priv->rfkill, !result);2070}2071 2072static int asus_rfkill_wlan_set(void *data, bool blocked)2073{2074 struct asus_rfkill *priv = data;2075 struct asus_wmi *asus = priv->asus;2076 int ret;2077 2078 /*2079 * This handler is enabled only if hotplug is enabled.2080 * In this case, the asus_wmi_set_devstate() will2081 * trigger a wmi notification and we need to wait2082 * this call to finish before being able to call2083 * any wmi method2084 */2085 mutex_lock(&asus->wmi_lock);2086 ret = asus_rfkill_set(data, blocked);2087 mutex_unlock(&asus->wmi_lock);2088 return ret;2089}2090 2091static const struct rfkill_ops asus_rfkill_wlan_ops = {2092 .set_block = asus_rfkill_wlan_set,2093 .query = asus_rfkill_query,2094};2095 2096static const struct rfkill_ops asus_rfkill_ops = {2097 .set_block = asus_rfkill_set,2098 .query = asus_rfkill_query,2099};2100 2101static int asus_new_rfkill(struct asus_wmi *asus,2102 struct asus_rfkill *arfkill,2103 const char *name, enum rfkill_type type, int dev_id)2104{2105 int result = asus_wmi_get_devstate_simple(asus, dev_id);2106 struct rfkill **rfkill = &arfkill->rfkill;2107 2108 if (result < 0)2109 return result;2110 2111 arfkill->dev_id = dev_id;2112 arfkill->asus = asus;2113 2114 if (dev_id == ASUS_WMI_DEVID_WLAN &&2115 asus->driver->quirks->hotplug_wireless)2116 *rfkill = rfkill_alloc(name, &asus->platform_device->dev, type,2117 &asus_rfkill_wlan_ops, arfkill);2118 else2119 *rfkill = rfkill_alloc(name, &asus->platform_device->dev, type,2120 &asus_rfkill_ops, arfkill);2121 2122 if (!*rfkill)2123 return -EINVAL;2124 2125 if ((dev_id == ASUS_WMI_DEVID_WLAN) &&2126 (asus->driver->quirks->wapf > 0))2127 rfkill_set_led_trigger_name(*rfkill, "asus-wlan");2128 2129 rfkill_init_sw_state(*rfkill, !result);2130 result = rfkill_register(*rfkill);2131 if (result) {2132 rfkill_destroy(*rfkill);2133 *rfkill = NULL;2134 return result;2135 }2136 return 0;2137}2138 2139static void asus_wmi_rfkill_exit(struct asus_wmi *asus)2140{2141 if (asus->driver->wlan_ctrl_by_user && ashs_present())2142 return;2143 2144 asus_unregister_rfkill_notifier(asus, "\\_SB.PCI0.P0P5");2145 asus_unregister_rfkill_notifier(asus, "\\_SB.PCI0.P0P6");2146 asus_unregister_rfkill_notifier(asus, "\\_SB.PCI0.P0P7");2147 if (asus->wlan.rfkill) {2148 rfkill_unregister(asus->wlan.rfkill);2149 rfkill_destroy(asus->wlan.rfkill);2150 asus->wlan.rfkill = NULL;2151 }2152 /*2153 * Refresh pci hotplug in case the rfkill state was changed after2154 * asus_unregister_rfkill_notifier()2155 */2156 asus_rfkill_hotplug(asus);2157 if (asus->hotplug_slot.ops)2158 pci_hp_deregister(&asus->hotplug_slot);2159 if (asus->hotplug_workqueue)2160 destroy_workqueue(asus->hotplug_workqueue);2161 2162 if (asus->bluetooth.rfkill) {2163 rfkill_unregister(asus->bluetooth.rfkill);2164 rfkill_destroy(asus->bluetooth.rfkill);2165 asus->bluetooth.rfkill = NULL;2166 }2167 if (asus->wimax.rfkill) {2168 rfkill_unregister(asus->wimax.rfkill);2169 rfkill_destroy(asus->wimax.rfkill);2170 asus->wimax.rfkill = NULL;2171 }2172 if (asus->wwan3g.rfkill) {2173 rfkill_unregister(asus->wwan3g.rfkill);2174 rfkill_destroy(asus->wwan3g.rfkill);2175 asus->wwan3g.rfkill = NULL;2176 }2177 if (asus->gps.rfkill) {2178 rfkill_unregister(asus->gps.rfkill);2179 rfkill_destroy(asus->gps.rfkill);2180 asus->gps.rfkill = NULL;2181 }2182 if (asus->uwb.rfkill) {2183 rfkill_unregister(asus->uwb.rfkill);2184 rfkill_destroy(asus->uwb.rfkill);2185 asus->uwb.rfkill = NULL;2186 }2187}2188 2189static int asus_wmi_rfkill_init(struct asus_wmi *asus)2190{2191 int result = 0;2192 2193 mutex_init(&asus->hotplug_lock);2194 mutex_init(&asus->wmi_lock);2195 2196 result = asus_new_rfkill(asus, &asus->wlan, "asus-wlan",2197 RFKILL_TYPE_WLAN, ASUS_WMI_DEVID_WLAN);2198 2199 if (result && result != -ENODEV)2200 goto exit;2201 2202 result = asus_new_rfkill(asus, &asus->bluetooth,2203 "asus-bluetooth", RFKILL_TYPE_BLUETOOTH,2204 ASUS_WMI_DEVID_BLUETOOTH);2205 2206 if (result && result != -ENODEV)2207 goto exit;2208 2209 result = asus_new_rfkill(asus, &asus->wimax, "asus-wimax",2210 RFKILL_TYPE_WIMAX, ASUS_WMI_DEVID_WIMAX);2211 2212 if (result && result != -ENODEV)2213 goto exit;2214 2215 result = asus_new_rfkill(asus, &asus->wwan3g, "asus-wwan3g",2216 RFKILL_TYPE_WWAN, ASUS_WMI_DEVID_WWAN3G);2217 2218 if (result && result != -ENODEV)2219 goto exit;2220 2221 result = asus_new_rfkill(asus, &asus->gps, "asus-gps",2222 RFKILL_TYPE_GPS, ASUS_WMI_DEVID_GPS);2223 2224 if (result && result != -ENODEV)2225 goto exit;2226 2227 result = asus_new_rfkill(asus, &asus->uwb, "asus-uwb",2228 RFKILL_TYPE_UWB, ASUS_WMI_DEVID_UWB);2229 2230 if (result && result != -ENODEV)2231 goto exit;2232 2233 if (!asus->driver->quirks->hotplug_wireless)2234 goto exit;2235 2236 result = asus_setup_pci_hotplug(asus);2237 /*2238 * If we get -EBUSY then something else is handling the PCI hotplug -2239 * don't fail in this case2240 */2241 if (result == -EBUSY)2242 result = 0;2243 2244 asus_register_rfkill_notifier(asus, "\\_SB.PCI0.P0P5");2245 asus_register_rfkill_notifier(asus, "\\_SB.PCI0.P0P6");2246 asus_register_rfkill_notifier(asus, "\\_SB.PCI0.P0P7");2247 /*2248 * Refresh pci hotplug in case the rfkill state was changed during2249 * setup.2250 */2251 asus_rfkill_hotplug(asus);2252 2253exit:2254 if (result && result != -ENODEV)2255 asus_wmi_rfkill_exit(asus);2256 2257 if (result == -ENODEV)2258 result = 0;2259 2260 return result;2261}2262 2263/* Panel Overdrive ************************************************************/2264static ssize_t panel_od_show(struct device *dev,2265 struct device_attribute *attr, char *buf)2266{2267 struct asus_wmi *asus = dev_get_drvdata(dev);2268 int result;2269 2270 result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_PANEL_OD);2271 if (result < 0)2272 return result;2273 2274 return sysfs_emit(buf, "%d\n", result);2275}2276 2277static ssize_t panel_od_store(struct device *dev,2278 struct device_attribute *attr,2279 const char *buf, size_t count)2280{2281 int result, err;2282 u32 overdrive;2283 2284 struct asus_wmi *asus = dev_get_drvdata(dev);2285 2286 result = kstrtou32(buf, 10, &overdrive);2287 if (result)2288 return result;2289 2290 if (overdrive > 1)2291 return -EINVAL;2292 2293 err = asus_wmi_set_devstate(ASUS_WMI_DEVID_PANEL_OD, overdrive, &result);2294 2295 if (err) {2296 pr_warn("Failed to set panel overdrive: %d\n", err);2297 return err;2298 }2299 2300 if (result > 1) {2301 pr_warn("Failed to set panel overdrive (result): 0x%x\n", result);2302 return -EIO;2303 }2304 2305 sysfs_notify(&asus->platform_device->dev.kobj, NULL, "panel_od");2306 2307 return count;2308}2309static DEVICE_ATTR_RW(panel_od);2310 2311/* Bootup sound ***************************************************************/2312 2313static ssize_t boot_sound_show(struct device *dev,2314 struct device_attribute *attr, char *buf)2315{2316 struct asus_wmi *asus = dev_get_drvdata(dev);2317 int result;2318 2319 result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_BOOT_SOUND);2320 if (result < 0)2321 return result;2322 2323 return sysfs_emit(buf, "%d\n", result);2324}2325 2326static ssize_t boot_sound_store(struct device *dev,2327 struct device_attribute *attr,2328 const char *buf, size_t count)2329{2330 int result, err;2331 u32 snd;2332 2333 struct asus_wmi *asus = dev_get_drvdata(dev);2334 2335 result = kstrtou32(buf, 10, &snd);2336 if (result)2337 return result;2338 2339 if (snd > 1)2340 return -EINVAL;2341 2342 err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BOOT_SOUND, snd, &result);2343 if (err) {2344 pr_warn("Failed to set boot sound: %d\n", err);2345 return err;2346 }2347 2348 if (result > 1) {2349 pr_warn("Failed to set panel boot sound (result): 0x%x\n", result);2350 return -EIO;2351 }2352 2353 sysfs_notify(&asus->platform_device->dev.kobj, NULL, "boot_sound");2354 2355 return count;2356}2357static DEVICE_ATTR_RW(boot_sound);2358 2359/* Mini-LED mode **************************************************************/2360static ssize_t mini_led_mode_show(struct device *dev,2361 struct device_attribute *attr, char *buf)2362{2363 struct asus_wmi *asus = dev_get_drvdata(dev);2364 u32 value;2365 int err;2366 2367 err = asus_wmi_get_devstate(asus, asus->mini_led_dev_id, &value);2368 if (err < 0)2369 return err;2370 value = value & ASUS_MINI_LED_MODE_MASK;2371 2372 /*2373 * Remap the mode values to match previous generation mini-led. The last gen2374 * WMI 0 == off, while on this version WMI 2 ==off (flipped).2375 */2376 if (asus->mini_led_dev_id == ASUS_WMI_DEVID_MINI_LED_MODE2) {2377 switch (value) {2378 case ASUS_MINI_LED_2024_WEAK:2379 value = ASUS_MINI_LED_ON;2380 break;2381 case ASUS_MINI_LED_2024_STRONG:2382 value = ASUS_MINI_LED_STRONG_MODE;2383 break;2384 case ASUS_MINI_LED_2024_OFF:2385 value = ASUS_MINI_LED_OFF;2386 break;2387 }2388 }2389 2390 return sysfs_emit(buf, "%d\n", value);2391}2392 2393static ssize_t mini_led_mode_store(struct device *dev,2394 struct device_attribute *attr,2395 const char *buf, size_t count)2396{2397 int result, err;2398 u32 mode;2399 2400 struct asus_wmi *asus = dev_get_drvdata(dev);2401 2402 result = kstrtou32(buf, 10, &mode);2403 if (result)2404 return result;2405 2406 if (asus->mini_led_dev_id == ASUS_WMI_DEVID_MINI_LED_MODE &&2407 mode > ASUS_MINI_LED_ON)2408 return -EINVAL;2409 if (asus->mini_led_dev_id == ASUS_WMI_DEVID_MINI_LED_MODE2 &&2410 mode > ASUS_MINI_LED_STRONG_MODE)2411 return -EINVAL;2412 2413 /*2414 * Remap the mode values so expected behaviour is the same as the last2415 * generation of mini-LED with 0 == off, 1 == on.2416 */2417 if (asus->mini_led_dev_id == ASUS_WMI_DEVID_MINI_LED_MODE2) {2418 switch (mode) {2419 case ASUS_MINI_LED_OFF:2420 mode = ASUS_MINI_LED_2024_OFF;2421 break;2422 case ASUS_MINI_LED_ON:2423 mode = ASUS_MINI_LED_2024_WEAK;2424 break;2425 case ASUS_MINI_LED_STRONG_MODE:2426 mode = ASUS_MINI_LED_2024_STRONG;2427 break;2428 }2429 }2430 2431 err = asus_wmi_set_devstate(asus->mini_led_dev_id, mode, &result);2432 if (err) {2433 pr_warn("Failed to set mini-LED: %d\n", err);2434 return err;2435 }2436 2437 if (result > 1) {2438 pr_warn("Failed to set mini-LED mode (result): 0x%x\n", result);2439 return -EIO;2440 }2441 2442 sysfs_notify(&asus->platform_device->dev.kobj, NULL, "mini_led_mode");2443 2444 return count;2445}2446static DEVICE_ATTR_RW(mini_led_mode);2447 2448static ssize_t available_mini_led_mode_show(struct device *dev,2449 struct device_attribute *attr, char *buf)2450{2451 struct asus_wmi *asus = dev_get_drvdata(dev);2452 2453 switch (asus->mini_led_dev_id) {2454 case ASUS_WMI_DEVID_MINI_LED_MODE:2455 return sysfs_emit(buf, "0 1\n");2456 case ASUS_WMI_DEVID_MINI_LED_MODE2:2457 return sysfs_emit(buf, "0 1 2\n");2458 }2459 2460 return sysfs_emit(buf, "0\n");2461}2462 2463static DEVICE_ATTR_RO(available_mini_led_mode);2464 2465/* Quirks *********************************************************************/2466 2467static void asus_wmi_set_xusb2pr(struct asus_wmi *asus)2468{2469 struct pci_dev *xhci_pdev;2470 u32 orig_ports_available;2471 u32 ports_available = asus->driver->quirks->xusb2pr;2472 2473 xhci_pdev = pci_get_device(PCI_VENDOR_ID_INTEL,2474 PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI,2475 NULL);2476 2477 if (!xhci_pdev)2478 return;2479 2480 pci_read_config_dword(xhci_pdev, USB_INTEL_XUSB2PR,2481 &orig_ports_available);2482 2483 pci_write_config_dword(xhci_pdev, USB_INTEL_XUSB2PR,2484 cpu_to_le32(ports_available));2485 2486 pci_dev_put(xhci_pdev);2487 2488 pr_info("set USB_INTEL_XUSB2PR old: 0x%04x, new: 0x%04x\n",2489 orig_ports_available, ports_available);2490}2491 2492/*2493 * Some devices dont support or have borcken get_als method2494 * but still support set method.2495 */2496static void asus_wmi_set_als(void)2497{2498 asus_wmi_set_devstate(ASUS_WMI_DEVID_ALS_ENABLE, 1, NULL);2499}2500 2501/* Hwmon device ***************************************************************/2502 2503static int asus_agfn_fan_speed_read(struct asus_wmi *asus, int fan,2504 int *speed)2505{2506 struct agfn_fan_args args = {2507 .agfn.len = sizeof(args),2508 .agfn.mfun = ASUS_FAN_MFUN,2509 .agfn.sfun = ASUS_FAN_SFUN_READ,2510 .fan = fan,2511 .speed = 0,2512 };2513 struct acpi_buffer input = { (acpi_size) sizeof(args), &args };2514 int status;2515 2516 if (fan != 1)2517 return -EINVAL;2518 2519 status = asus_wmi_evaluate_method_agfn(input);2520 2521 if (status || args.agfn.err)2522 return -ENXIO;2523 2524 if (speed)2525 *speed = args.speed;2526 2527 return 0;2528}2529 2530static int asus_agfn_fan_speed_write(struct asus_wmi *asus, int fan,2531 int *speed)2532{2533 struct agfn_fan_args args = {2534 .agfn.len = sizeof(args),2535 .agfn.mfun = ASUS_FAN_MFUN,2536 .agfn.sfun = ASUS_FAN_SFUN_WRITE,2537 .fan = fan,2538 .speed = speed ? *speed : 0,2539 };2540 struct acpi_buffer input = { (acpi_size) sizeof(args), &args };2541 int status;2542 2543 /* 1: for setting 1st fan's speed 0: setting auto mode */2544 if (fan != 1 && fan != 0)2545 return -EINVAL;2546 2547 status = asus_wmi_evaluate_method_agfn(input);2548 2549 if (status || args.agfn.err)2550 return -ENXIO;2551 2552 if (speed && fan == 1)2553 asus->agfn_pwm = *speed;2554 2555 return 0;2556}2557 2558/*2559 * Check if we can read the speed of one fan. If true we assume we can also2560 * control it.2561 */2562static bool asus_wmi_has_agfn_fan(struct asus_wmi *asus)2563{2564 int status;2565 int speed;2566 u32 value;2567 2568 status = asus_agfn_fan_speed_read(asus, 1, &speed);2569 if (status != 0)2570 return false;2571 2572 status = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_FAN_CTRL, &value);2573 if (status != 0)2574 return false;2575 2576 /*2577 * We need to find a better way, probably using sfun,2578 * bits or spec ...2579 * Currently we disable it if:2580 * - ASUS_WMI_UNSUPPORTED_METHOD is returned2581 * - reverved bits are non-zero2582 * - sfun and presence bit are not set2583 */2584 return !(value == ASUS_WMI_UNSUPPORTED_METHOD || value & 0xFFF800002585 || (!asus->sfun && !(value & ASUS_WMI_DSTS_PRESENCE_BIT)));2586}2587 2588static int asus_fan_set_auto(struct asus_wmi *asus)2589{2590 int status;2591 u32 retval;2592 2593 switch (asus->fan_type) {2594 case FAN_TYPE_SPEC83:2595 status = asus_wmi_set_devstate(ASUS_WMI_DEVID_CPU_FAN_CTRL,2596 0, &retval);2597 if (status)2598 return status;2599 2600 if (retval != 1)2601 return -EIO;2602 break;2603 2604 case FAN_TYPE_AGFN:2605 status = asus_agfn_fan_speed_write(asus, 0, NULL);2606 if (status)2607 return -ENXIO;2608 break;2609 2610 default:2611 return -ENXIO;2612 }2613 2614 /*2615 * Modern models like the G713 also have GPU fan control (this is not AGFN)2616 */2617 if (asus->gpu_fan_type == FAN_TYPE_SPEC83) {2618 status = asus_wmi_set_devstate(ASUS_WMI_DEVID_GPU_FAN_CTRL,2619 0, &retval);2620 if (status)2621 return status;2622 2623 if (retval != 1)2624 return -EIO;2625 }2626 2627 return 0;2628}2629 2630static ssize_t pwm1_show(struct device *dev,2631 struct device_attribute *attr,2632 char *buf)2633{2634 struct asus_wmi *asus = dev_get_drvdata(dev);2635 int err;2636 int value;2637 2638 /* If we already set a value then just return it */2639 if (asus->agfn_pwm >= 0)2640 return sysfs_emit(buf, "%d\n", asus->agfn_pwm);2641 2642 /*2643 * If we haven't set already set a value through the AGFN interface,2644 * we read a current value through the (now-deprecated) FAN_CTRL device.2645 */2646 err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_FAN_CTRL, &value);2647 if (err < 0)2648 return err;2649 2650 value &= 0xFF;2651 2652 if (value == 1) /* Low Speed */2653 value = 85;2654 else if (value == 2)2655 value = 170;2656 else if (value == 3)2657 value = 255;2658 else if (value) {2659 pr_err("Unknown fan speed %#x\n", value);2660 value = -1;2661 }2662 2663 return sysfs_emit(buf, "%d\n", value);2664}2665 2666static ssize_t pwm1_store(struct device *dev,2667 struct device_attribute *attr,2668 const char *buf, size_t count) {2669 struct asus_wmi *asus = dev_get_drvdata(dev);2670 int value;2671 int state;2672 int ret;2673 2674 ret = kstrtouint(buf, 10, &value);2675 if (ret)2676 return ret;2677 2678 value = clamp(value, 0, 255);2679 2680 state = asus_agfn_fan_speed_write(asus, 1, &value);2681 if (state)2682 pr_warn("Setting fan speed failed: %d\n", state);2683 else2684 asus->fan_pwm_mode = ASUS_FAN_CTRL_MANUAL;2685 2686 return count;2687}2688 2689static ssize_t fan1_input_show(struct device *dev,2690 struct device_attribute *attr,2691 char *buf)2692{2693 struct asus_wmi *asus = dev_get_drvdata(dev);2694 int value;2695 int ret;2696 2697 switch (asus->fan_type) {2698 case FAN_TYPE_SPEC83:2699 ret = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_CPU_FAN_CTRL,2700 &value);2701 if (ret < 0)2702 return ret;2703 2704 value &= 0xffff;2705 break;2706 2707 case FAN_TYPE_AGFN:2708 /* no speed readable on manual mode */2709 if (asus->fan_pwm_mode == ASUS_FAN_CTRL_MANUAL)2710 return -ENXIO;2711 2712 ret = asus_agfn_fan_speed_read(asus, 1, &value);2713 if (ret) {2714 pr_warn("reading fan speed failed: %d\n", ret);2715 return -ENXIO;2716 }2717 break;2718 2719 default:2720 return -ENXIO;2721 }2722 2723 return sysfs_emit(buf, "%d\n", value < 0 ? -1 : value * 100);2724}2725 2726static ssize_t pwm1_enable_show(struct device *dev,2727 struct device_attribute *attr,2728 char *buf)2729{2730 struct asus_wmi *asus = dev_get_drvdata(dev);2731 2732 /*2733 * Just read back the cached pwm mode.2734 *2735 * For the CPU_FAN device, the spec indicates that we should be2736 * able to read the device status and consult bit 19 to see if we2737 * are in Full On or Automatic mode. However, this does not work2738 * in practice on X532FL at least (the bit is always 0) and there's2739 * also nothing in the DSDT to indicate that this behaviour exists.2740 */2741 return sysfs_emit(buf, "%d\n", asus->fan_pwm_mode);2742}2743 2744static ssize_t pwm1_enable_store(struct device *dev,2745 struct device_attribute *attr,2746 const char *buf, size_t count)2747{2748 struct asus_wmi *asus = dev_get_drvdata(dev);2749 int status = 0;2750 int state;2751 int value;2752 int ret;2753 u32 retval;2754 2755 ret = kstrtouint(buf, 10, &state);2756 if (ret)2757 return ret;2758 2759 if (asus->fan_type == FAN_TYPE_SPEC83) {2760 switch (state) { /* standard documented hwmon values */2761 case ASUS_FAN_CTRL_FULLSPEED:2762 value = 1;2763 break;2764 case ASUS_FAN_CTRL_AUTO:2765 value = 0;2766 break;2767 default:2768 return -EINVAL;2769 }2770 2771 ret = asus_wmi_set_devstate(ASUS_WMI_DEVID_CPU_FAN_CTRL,2772 value, &retval);2773 if (ret)2774 return ret;2775 2776 if (retval != 1)2777 return -EIO;2778 } else if (asus->fan_type == FAN_TYPE_AGFN) {2779 switch (state) {2780 case ASUS_FAN_CTRL_MANUAL:2781 break;2782 2783 case ASUS_FAN_CTRL_AUTO:2784 status = asus_fan_set_auto(asus);2785 if (status)2786 return status;2787 break;2788 2789 default:2790 return -EINVAL;2791 }2792 }2793 2794 asus->fan_pwm_mode = state;2795 2796 /* Must set to disabled if mode is toggled */2797 if (asus->cpu_fan_curve_available)2798 asus->custom_fan_curves[FAN_CURVE_DEV_CPU].enabled = false;2799 if (asus->gpu_fan_curve_available)2800 asus->custom_fan_curves[FAN_CURVE_DEV_GPU].enabled = false;2801 if (asus->mid_fan_curve_available)2802 asus->custom_fan_curves[FAN_CURVE_DEV_MID].enabled = false;2803 2804 return count;2805}2806 2807static ssize_t asus_hwmon_temp1(struct device *dev,2808 struct device_attribute *attr,2809 char *buf)2810{2811 struct asus_wmi *asus = dev_get_drvdata(dev);2812 u32 value;2813 int err;2814 2815 err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_THERMAL_CTRL, &value);2816 if (err < 0)2817 return err;2818 2819 return sysfs_emit(buf, "%ld\n",2820 deci_kelvin_to_millicelsius(value & 0xFFFF));2821}2822 2823/* GPU fan on modern ROG laptops */2824static ssize_t fan2_input_show(struct device *dev,2825 struct device_attribute *attr,2826 char *buf)2827{2828 struct asus_wmi *asus = dev_get_drvdata(dev);2829 int value;2830 int ret;2831 2832 ret = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_GPU_FAN_CTRL, &value);2833 if (ret < 0)2834 return ret;2835 2836 value &= 0xffff;2837 2838 return sysfs_emit(buf, "%d\n", value * 100);2839}2840 2841/* Middle/Center fan on modern ROG laptops */2842static ssize_t fan3_input_show(struct device *dev,2843 struct device_attribute *attr,2844 char *buf)2845{2846 struct asus_wmi *asus = dev_get_drvdata(dev);2847 int value;2848 int ret;2849 2850 ret = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_MID_FAN_CTRL, &value);2851 if (ret < 0)2852 return ret;2853 2854 value &= 0xffff;2855 2856 return sysfs_emit(buf, "%d\n", value * 100);2857}2858 2859static ssize_t pwm2_enable_show(struct device *dev,2860 struct device_attribute *attr,2861 char *buf)2862{2863 struct asus_wmi *asus = dev_get_drvdata(dev);2864 2865 return sysfs_emit(buf, "%d\n", asus->gpu_fan_pwm_mode);2866}2867 2868static ssize_t pwm2_enable_store(struct device *dev,2869 struct device_attribute *attr,2870 const char *buf, size_t count)2871{2872 struct asus_wmi *asus = dev_get_drvdata(dev);2873 int state;2874 int value;2875 int ret;2876 u32 retval;2877 2878 ret = kstrtouint(buf, 10, &state);2879 if (ret)2880 return ret;2881 2882 switch (state) { /* standard documented hwmon values */2883 case ASUS_FAN_CTRL_FULLSPEED:2884 value = 1;2885 break;2886 case ASUS_FAN_CTRL_AUTO:2887 value = 0;2888 break;2889 default:2890 return -EINVAL;2891 }2892 2893 ret = asus_wmi_set_devstate(ASUS_WMI_DEVID_GPU_FAN_CTRL,2894 value, &retval);2895 if (ret)2896 return ret;2897 2898 if (retval != 1)2899 return -EIO;2900 2901 asus->gpu_fan_pwm_mode = state;2902 return count;2903}2904 2905static ssize_t pwm3_enable_show(struct device *dev,2906 struct device_attribute *attr,2907 char *buf)2908{2909 struct asus_wmi *asus = dev_get_drvdata(dev);2910 2911 return sysfs_emit(buf, "%d\n", asus->mid_fan_pwm_mode);2912}2913 2914static ssize_t pwm3_enable_store(struct device *dev,2915 struct device_attribute *attr,2916 const char *buf, size_t count)2917{2918 struct asus_wmi *asus = dev_get_drvdata(dev);2919 int state;2920 int value;2921 int ret;2922 u32 retval;2923 2924 ret = kstrtouint(buf, 10, &state);2925 if (ret)2926 return ret;2927 2928 switch (state) { /* standard documented hwmon values */2929 case ASUS_FAN_CTRL_FULLSPEED:2930 value = 1;2931 break;2932 case ASUS_FAN_CTRL_AUTO:2933 value = 0;2934 break;2935 default:2936 return -EINVAL;2937 }2938 2939 ret = asus_wmi_set_devstate(ASUS_WMI_DEVID_MID_FAN_CTRL,2940 value, &retval);2941 if (ret)2942 return ret;2943 2944 if (retval != 1)2945 return -EIO;2946 2947 asus->mid_fan_pwm_mode = state;2948 return count;2949}2950 2951/* Fan1 */2952static DEVICE_ATTR_RW(pwm1);2953static DEVICE_ATTR_RW(pwm1_enable);2954static DEVICE_ATTR_RO(fan1_input);2955static DEVICE_STRING_ATTR_RO(fan1_label, 0444, ASUS_FAN_DESC);2956 2957/* Fan2 - GPU fan */2958static DEVICE_ATTR_RW(pwm2_enable);2959static DEVICE_ATTR_RO(fan2_input);2960static DEVICE_STRING_ATTR_RO(fan2_label, 0444, ASUS_GPU_FAN_DESC);2961/* Fan3 - Middle/center fan */2962static DEVICE_ATTR_RW(pwm3_enable);2963static DEVICE_ATTR_RO(fan3_input);2964static DEVICE_STRING_ATTR_RO(fan3_label, 0444, ASUS_MID_FAN_DESC);2965 2966/* Temperature */2967static DEVICE_ATTR(temp1_input, S_IRUGO, asus_hwmon_temp1, NULL);2968 2969static struct attribute *hwmon_attributes[] = {2970 &dev_attr_pwm1.attr,2971 &dev_attr_pwm1_enable.attr,2972 &dev_attr_pwm2_enable.attr,2973 &dev_attr_pwm3_enable.attr,2974 &dev_attr_fan1_input.attr,2975 &dev_attr_fan1_label.attr.attr,2976 &dev_attr_fan2_input.attr,2977 &dev_attr_fan2_label.attr.attr,2978 &dev_attr_fan3_input.attr,2979 &dev_attr_fan3_label.attr.attr,2980 2981 &dev_attr_temp1_input.attr,2982 NULL2983};2984 2985static umode_t asus_hwmon_sysfs_is_visible(struct kobject *kobj,2986 struct attribute *attr, int idx)2987{2988 struct device *dev = kobj_to_dev(kobj);2989 struct asus_wmi *asus = dev_get_drvdata(dev->parent);2990 u32 value = ASUS_WMI_UNSUPPORTED_METHOD;2991 2992 if (attr == &dev_attr_pwm1.attr) {2993 if (asus->fan_type != FAN_TYPE_AGFN)2994 return 0;2995 } else if (attr == &dev_attr_fan1_input.attr2996 || attr == &dev_attr_fan1_label.attr.attr2997 || attr == &dev_attr_pwm1_enable.attr) {2998 if (asus->fan_type == FAN_TYPE_NONE)2999 return 0;3000 } else if (attr == &dev_attr_fan2_input.attr3001 || attr == &dev_attr_fan2_label.attr.attr3002 || attr == &dev_attr_pwm2_enable.attr) {3003 if (asus->gpu_fan_type == FAN_TYPE_NONE)3004 return 0;3005 } else if (attr == &dev_attr_fan3_input.attr3006 || attr == &dev_attr_fan3_label.attr.attr3007 || attr == &dev_attr_pwm3_enable.attr) {3008 if (asus->mid_fan_type == FAN_TYPE_NONE)3009 return 0;3010 } else if (attr == &dev_attr_temp1_input.attr) {3011 int err = asus_wmi_get_devstate(asus,3012 ASUS_WMI_DEVID_THERMAL_CTRL,3013 &value);3014 3015 if (err < 0)3016 return 0; /* can't return negative here */3017 3018 /*3019 * If the temperature value in deci-Kelvin is near the absolute3020 * zero temperature, something is clearly wrong3021 */3022 if (value == 0 || value == 1)3023 return 0;3024 }3025 3026 return attr->mode;3027}3028 3029static const struct attribute_group hwmon_attribute_group = {3030 .is_visible = asus_hwmon_sysfs_is_visible,3031 .attrs = hwmon_attributes3032};3033__ATTRIBUTE_GROUPS(hwmon_attribute);3034 3035static int asus_wmi_hwmon_init(struct asus_wmi *asus)3036{3037 struct device *dev = &asus->platform_device->dev;3038 struct device *hwmon;3039 3040 hwmon = devm_hwmon_device_register_with_groups(dev, "asus", asus,3041 hwmon_attribute_groups);3042 3043 if (IS_ERR(hwmon)) {3044 pr_err("Could not register asus hwmon device\n");3045 return PTR_ERR(hwmon);3046 }3047 return 0;3048}3049 3050static int asus_wmi_fan_init(struct asus_wmi *asus)3051{3052 asus->gpu_fan_type = FAN_TYPE_NONE;3053 asus->mid_fan_type = FAN_TYPE_NONE;3054 asus->fan_type = FAN_TYPE_NONE;3055 asus->agfn_pwm = -1;3056 3057 if (asus->driver->quirks->wmi_ignore_fan)3058 asus->fan_type = FAN_TYPE_NONE;3059 else if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_CPU_FAN_CTRL))3060 asus->fan_type = FAN_TYPE_SPEC83;3061 else if (asus_wmi_has_agfn_fan(asus))3062 asus->fan_type = FAN_TYPE_AGFN;3063 3064 /* Modern models like G713 also have GPU fan control */3065 if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_GPU_FAN_CTRL))3066 asus->gpu_fan_type = FAN_TYPE_SPEC83;3067 3068 /* Some models also have a center/middle fan */3069 if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_MID_FAN_CTRL))3070 asus->mid_fan_type = FAN_TYPE_SPEC83;3071 3072 if (asus->fan_type == FAN_TYPE_NONE)3073 return -ENODEV;3074 3075 asus_fan_set_auto(asus);3076 asus->fan_pwm_mode = ASUS_FAN_CTRL_AUTO;3077 return 0;3078}3079 3080/* Fan mode *******************************************************************/3081 3082static int fan_boost_mode_check_present(struct asus_wmi *asus)3083{3084 u32 result;3085 int err;3086 3087 asus->fan_boost_mode_available = false;3088 3089 err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_FAN_BOOST_MODE,3090 &result);3091 if (err) {3092 if (err == -ENODEV)3093 return 0;3094 else3095 return err;3096 }3097 3098 if ((result & ASUS_WMI_DSTS_PRESENCE_BIT) &&3099 (result & ASUS_FAN_BOOST_MODES_MASK)) {3100 asus->fan_boost_mode_available = true;3101 asus->fan_boost_mode_mask = result & ASUS_FAN_BOOST_MODES_MASK;3102 }3103 3104 return 0;3105}3106 3107static int fan_boost_mode_write(struct asus_wmi *asus)3108{3109 u32 retval;3110 u8 value;3111 int err;3112 3113 value = asus->fan_boost_mode;3114 3115 pr_info("Set fan boost mode: %u\n", value);3116 err = asus_wmi_set_devstate(ASUS_WMI_DEVID_FAN_BOOST_MODE, value,3117 &retval);3118 3119 sysfs_notify(&asus->platform_device->dev.kobj, NULL,3120 "fan_boost_mode");3121 3122 if (err) {3123 pr_warn("Failed to set fan boost mode: %d\n", err);3124 return err;3125 }3126 3127 if (retval != 1) {3128 pr_warn("Failed to set fan boost mode (retval): 0x%x\n",3129 retval);3130 return -EIO;3131 }3132 3133 return 0;3134}3135 3136static int fan_boost_mode_switch_next(struct asus_wmi *asus)3137{3138 u8 mask = asus->fan_boost_mode_mask;3139 3140 if (asus->fan_boost_mode == ASUS_FAN_BOOST_MODE_NORMAL) {3141 if (mask & ASUS_FAN_BOOST_MODE_OVERBOOST_MASK)3142 asus->fan_boost_mode = ASUS_FAN_BOOST_MODE_OVERBOOST;3143 else if (mask & ASUS_FAN_BOOST_MODE_SILENT_MASK)3144 asus->fan_boost_mode = ASUS_FAN_BOOST_MODE_SILENT;3145 } else if (asus->fan_boost_mode == ASUS_FAN_BOOST_MODE_OVERBOOST) {3146 if (mask & ASUS_FAN_BOOST_MODE_SILENT_MASK)3147 asus->fan_boost_mode = ASUS_FAN_BOOST_MODE_SILENT;3148 else3149 asus->fan_boost_mode = ASUS_FAN_BOOST_MODE_NORMAL;3150 } else {3151 asus->fan_boost_mode = ASUS_FAN_BOOST_MODE_NORMAL;3152 }3153 3154 return fan_boost_mode_write(asus);3155}3156 3157static ssize_t fan_boost_mode_show(struct device *dev,3158 struct device_attribute *attr, char *buf)3159{3160 struct asus_wmi *asus = dev_get_drvdata(dev);3161 3162 return sysfs_emit(buf, "%d\n", asus->fan_boost_mode);3163}3164 3165static ssize_t fan_boost_mode_store(struct device *dev,3166 struct device_attribute *attr,3167 const char *buf, size_t count)3168{3169 struct asus_wmi *asus = dev_get_drvdata(dev);3170 u8 mask = asus->fan_boost_mode_mask;3171 u8 new_mode;3172 int result;3173 3174 result = kstrtou8(buf, 10, &new_mode);3175 if (result < 0) {3176 pr_warn("Trying to store invalid value\n");3177 return result;3178 }3179 3180 if (new_mode == ASUS_FAN_BOOST_MODE_OVERBOOST) {3181 if (!(mask & ASUS_FAN_BOOST_MODE_OVERBOOST_MASK))3182 return -EINVAL;3183 } else if (new_mode == ASUS_FAN_BOOST_MODE_SILENT) {3184 if (!(mask & ASUS_FAN_BOOST_MODE_SILENT_MASK))3185 return -EINVAL;3186 } else if (new_mode != ASUS_FAN_BOOST_MODE_NORMAL) {3187 return -EINVAL;3188 }3189 3190 asus->fan_boost_mode = new_mode;3191 fan_boost_mode_write(asus);3192 3193 return count;3194}3195 3196// Fan boost mode: 0 - normal, 1 - overboost, 2 - silent3197static DEVICE_ATTR_RW(fan_boost_mode);3198 3199/* Custom fan curves **********************************************************/3200 3201static void fan_curve_copy_from_buf(struct fan_curve_data *data, u8 *buf)3202{3203 int i;3204 3205 for (i = 0; i < FAN_CURVE_POINTS; i++) {3206 data->temps[i] = buf[i];3207 }3208 3209 for (i = 0; i < FAN_CURVE_POINTS; i++) {3210 data->percents[i] =3211 255 * buf[i + FAN_CURVE_POINTS] / 100;3212 }3213}3214 3215static int fan_curve_get_factory_default(struct asus_wmi *asus, u32 fan_dev)3216{3217 struct fan_curve_data *curves;3218 u8 buf[FAN_CURVE_BUF_LEN];3219 int err, fan_idx;3220 u8 mode = 0;3221 3222 if (asus->throttle_thermal_policy_dev)3223 mode = asus->throttle_thermal_policy_mode;3224 /* DEVID_<C/G>PU_FAN_CURVE is switched for OVERBOOST vs SILENT */3225 if (mode == 2)3226 mode = 1;3227 else if (mode == 1)3228 mode = 2;3229 3230 err = asus_wmi_evaluate_method_buf(asus->dsts_id, fan_dev, mode, buf,3231 FAN_CURVE_BUF_LEN);3232 if (err) {3233 pr_warn("%s (0x%08x) failed: %d\n", __func__, fan_dev, err);3234 return err;3235 }3236 3237 fan_idx = FAN_CURVE_DEV_CPU;3238 if (fan_dev == ASUS_WMI_DEVID_GPU_FAN_CURVE)3239 fan_idx = FAN_CURVE_DEV_GPU;3240 3241 if (fan_dev == ASUS_WMI_DEVID_MID_FAN_CURVE)3242 fan_idx = FAN_CURVE_DEV_MID;3243 3244 curves = &asus->custom_fan_curves[fan_idx];3245 curves->device_id = fan_dev;3246 3247 fan_curve_copy_from_buf(curves, buf);3248 return 0;3249}3250 3251/* Check if capability exists, and populate defaults */3252static int fan_curve_check_present(struct asus_wmi *asus, bool *available,3253 u32 fan_dev)3254{3255 int err;3256 3257 *available = false;3258 3259 if (asus->fan_type == FAN_TYPE_NONE)3260 return 0;3261 3262 err = fan_curve_get_factory_default(asus, fan_dev);3263 if (err) {3264 return 0;3265 }3266 3267 *available = true;3268 return 0;3269}3270 3271/* Determine which fan the attribute is for if SENSOR_ATTR */3272static struct fan_curve_data *fan_curve_attr_select(struct asus_wmi *asus,3273 struct device_attribute *attr)3274{3275 int index = to_sensor_dev_attr(attr)->index;3276 3277 return &asus->custom_fan_curves[index];3278}3279 3280/* Determine which fan the attribute is for if SENSOR_ATTR_2 */3281static struct fan_curve_data *fan_curve_attr_2_select(struct asus_wmi *asus,3282 struct device_attribute *attr)3283{3284 int nr = to_sensor_dev_attr_2(attr)->nr;3285 3286 return &asus->custom_fan_curves[nr & ~FAN_CURVE_PWM_MASK];3287}3288 3289static ssize_t fan_curve_show(struct device *dev,3290 struct device_attribute *attr, char *buf)3291{3292 struct sensor_device_attribute_2 *dev_attr = to_sensor_dev_attr_2(attr);3293 struct asus_wmi *asus = dev_get_drvdata(dev);3294 struct fan_curve_data *data;3295 int value, pwm, index;3296 3297 data = fan_curve_attr_2_select(asus, attr);3298 pwm = dev_attr->nr & FAN_CURVE_PWM_MASK;3299 index = dev_attr->index;3300 3301 if (pwm)3302 value = data->percents[index];3303 else3304 value = data->temps[index];3305 3306 return sysfs_emit(buf, "%d\n", value);3307}3308 3309/*3310 * "fan_dev" is the related WMI method such as ASUS_WMI_DEVID_CPU_FAN_CURVE.3311 */3312static int fan_curve_write(struct asus_wmi *asus,3313 struct fan_curve_data *data)3314{3315 u32 arg1 = 0, arg2 = 0, arg3 = 0, arg4 = 0;3316 u8 *percents = data->percents;3317 u8 *temps = data->temps;3318 int ret, i, shift = 0;3319 3320 if (!data->enabled)3321 return 0;3322 3323 for (i = 0; i < FAN_CURVE_POINTS / 2; i++) {3324 arg1 += (temps[i]) << shift;3325 arg2 += (temps[i + 4]) << shift;3326 /* Scale to percentage for device */3327 arg3 += (100 * percents[i] / 255) << shift;3328 arg4 += (100 * percents[i + 4] / 255) << shift;3329 shift += 8;3330 }3331 3332 return asus_wmi_evaluate_method5(ASUS_WMI_METHODID_DEVS,3333 data->device_id,3334 arg1, arg2, arg3, arg4, &ret);3335}3336 3337static ssize_t fan_curve_store(struct device *dev,3338 struct device_attribute *attr, const char *buf,3339 size_t count)3340{3341 struct sensor_device_attribute_2 *dev_attr = to_sensor_dev_attr_2(attr);3342 struct asus_wmi *asus = dev_get_drvdata(dev);3343 struct fan_curve_data *data;3344 int err, pwm, index;3345 u8 value;3346 3347 data = fan_curve_attr_2_select(asus, attr);3348 pwm = dev_attr->nr & FAN_CURVE_PWM_MASK;3349 index = dev_attr->index;3350 3351 err = kstrtou8(buf, 10, &value);3352 if (err < 0)3353 return err;3354 3355 if (pwm)3356 data->percents[index] = value;3357 else3358 data->temps[index] = value;3359 3360 /*3361 * Mark as disabled so the user has to explicitly enable to apply a3362 * changed fan curve. This prevents potential lockups from writing out3363 * many changes as one-write-per-change.3364 */3365 data->enabled = false;3366 3367 return count;3368}3369 3370static ssize_t fan_curve_enable_show(struct device *dev,3371 struct device_attribute *attr, char *buf)3372{3373 struct asus_wmi *asus = dev_get_drvdata(dev);3374 struct fan_curve_data *data;3375 int out = 2;3376 3377 data = fan_curve_attr_select(asus, attr);3378 3379 if (data->enabled)3380 out = 1;3381 3382 return sysfs_emit(buf, "%d\n", out);3383}3384 3385static ssize_t fan_curve_enable_store(struct device *dev,3386 struct device_attribute *attr,3387 const char *buf, size_t count)3388{3389 struct asus_wmi *asus = dev_get_drvdata(dev);3390 struct fan_curve_data *data;3391 int value, err;3392 3393 data = fan_curve_attr_select(asus, attr);3394 3395 err = kstrtoint(buf, 10, &value);3396 if (err < 0)3397 return err;3398 3399 switch (value) {3400 case 1:3401 data->enabled = true;3402 break;3403 case 2:3404 data->enabled = false;3405 break;3406 /*3407 * Auto + reset the fan curve data to defaults. Make it an explicit3408 * option so that users don't accidentally overwrite a set fan curve.3409 */3410 case 3:3411 err = fan_curve_get_factory_default(asus, data->device_id);3412 if (err)3413 return err;3414 data->enabled = false;3415 break;3416 default:3417 return -EINVAL;3418 }3419 3420 if (data->enabled) {3421 err = fan_curve_write(asus, data);3422 if (err)3423 return err;3424 } else {3425 /*3426 * For machines with throttle this is the only way to reset fans3427 * to default mode of operation (does not erase curve data).3428 */3429 if (asus->throttle_thermal_policy_dev) {3430 err = throttle_thermal_policy_write(asus);3431 if (err)3432 return err;3433 /* Similar is true for laptops with this fan */3434 } else if (asus->fan_type == FAN_TYPE_SPEC83) {3435 err = asus_fan_set_auto(asus);3436 if (err)3437 return err;3438 } else {3439 /* Safeguard against fautly ACPI tables */3440 err = fan_curve_get_factory_default(asus, data->device_id);3441 if (err)3442 return err;3443 err = fan_curve_write(asus, data);3444 if (err)3445 return err;3446 }3447 }3448 return count;3449}3450 3451/* CPU */3452static SENSOR_DEVICE_ATTR_RW(pwm1_enable, fan_curve_enable, FAN_CURVE_DEV_CPU);3453static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point1_temp, fan_curve,3454 FAN_CURVE_DEV_CPU, 0);3455static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point2_temp, fan_curve,3456 FAN_CURVE_DEV_CPU, 1);3457static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point3_temp, fan_curve,3458 FAN_CURVE_DEV_CPU, 2);3459static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point4_temp, fan_curve,3460 FAN_CURVE_DEV_CPU, 3);3461static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point5_temp, fan_curve,3462 FAN_CURVE_DEV_CPU, 4);3463static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point6_temp, fan_curve,3464 FAN_CURVE_DEV_CPU, 5);3465static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point7_temp, fan_curve,3466 FAN_CURVE_DEV_CPU, 6);3467static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point8_temp, fan_curve,3468 FAN_CURVE_DEV_CPU, 7);3469 3470static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point1_pwm, fan_curve,3471 FAN_CURVE_DEV_CPU | FAN_CURVE_PWM_MASK, 0);3472static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point2_pwm, fan_curve,3473 FAN_CURVE_DEV_CPU | FAN_CURVE_PWM_MASK, 1);3474static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point3_pwm, fan_curve,3475 FAN_CURVE_DEV_CPU | FAN_CURVE_PWM_MASK, 2);3476static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point4_pwm, fan_curve,3477 FAN_CURVE_DEV_CPU | FAN_CURVE_PWM_MASK, 3);3478static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point5_pwm, fan_curve,3479 FAN_CURVE_DEV_CPU | FAN_CURVE_PWM_MASK, 4);3480static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point6_pwm, fan_curve,3481 FAN_CURVE_DEV_CPU | FAN_CURVE_PWM_MASK, 5);3482static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point7_pwm, fan_curve,3483 FAN_CURVE_DEV_CPU | FAN_CURVE_PWM_MASK, 6);3484static SENSOR_DEVICE_ATTR_2_RW(pwm1_auto_point8_pwm, fan_curve,3485 FAN_CURVE_DEV_CPU | FAN_CURVE_PWM_MASK, 7);3486 3487/* GPU */3488static SENSOR_DEVICE_ATTR_RW(pwm2_enable, fan_curve_enable, FAN_CURVE_DEV_GPU);3489static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point1_temp, fan_curve,3490 FAN_CURVE_DEV_GPU, 0);3491static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point2_temp, fan_curve,3492 FAN_CURVE_DEV_GPU, 1);3493static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point3_temp, fan_curve,3494 FAN_CURVE_DEV_GPU, 2);3495static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point4_temp, fan_curve,3496 FAN_CURVE_DEV_GPU, 3);3497static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point5_temp, fan_curve,3498 FAN_CURVE_DEV_GPU, 4);3499static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point6_temp, fan_curve,3500 FAN_CURVE_DEV_GPU, 5);3501static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point7_temp, fan_curve,3502 FAN_CURVE_DEV_GPU, 6);3503static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point8_temp, fan_curve,3504 FAN_CURVE_DEV_GPU, 7);3505 3506static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point1_pwm, fan_curve,3507 FAN_CURVE_DEV_GPU | FAN_CURVE_PWM_MASK, 0);3508static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point2_pwm, fan_curve,3509 FAN_CURVE_DEV_GPU | FAN_CURVE_PWM_MASK, 1);3510static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point3_pwm, fan_curve,3511 FAN_CURVE_DEV_GPU | FAN_CURVE_PWM_MASK, 2);3512static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point4_pwm, fan_curve,3513 FAN_CURVE_DEV_GPU | FAN_CURVE_PWM_MASK, 3);3514static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point5_pwm, fan_curve,3515 FAN_CURVE_DEV_GPU | FAN_CURVE_PWM_MASK, 4);3516static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point6_pwm, fan_curve,3517 FAN_CURVE_DEV_GPU | FAN_CURVE_PWM_MASK, 5);3518static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point7_pwm, fan_curve,3519 FAN_CURVE_DEV_GPU | FAN_CURVE_PWM_MASK, 6);3520static SENSOR_DEVICE_ATTR_2_RW(pwm2_auto_point8_pwm, fan_curve,3521 FAN_CURVE_DEV_GPU | FAN_CURVE_PWM_MASK, 7);3522 3523/* MID */3524static SENSOR_DEVICE_ATTR_RW(pwm3_enable, fan_curve_enable, FAN_CURVE_DEV_MID);3525static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point1_temp, fan_curve,3526 FAN_CURVE_DEV_MID, 0);3527static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point2_temp, fan_curve,3528 FAN_CURVE_DEV_MID, 1);3529static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point3_temp, fan_curve,3530 FAN_CURVE_DEV_MID, 2);3531static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point4_temp, fan_curve,3532 FAN_CURVE_DEV_MID, 3);3533static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point5_temp, fan_curve,3534 FAN_CURVE_DEV_MID, 4);3535static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point6_temp, fan_curve,3536 FAN_CURVE_DEV_MID, 5);3537static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point7_temp, fan_curve,3538 FAN_CURVE_DEV_MID, 6);3539static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point8_temp, fan_curve,3540 FAN_CURVE_DEV_MID, 7);3541 3542static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point1_pwm, fan_curve,3543 FAN_CURVE_DEV_MID | FAN_CURVE_PWM_MASK, 0);3544static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point2_pwm, fan_curve,3545 FAN_CURVE_DEV_MID | FAN_CURVE_PWM_MASK, 1);3546static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point3_pwm, fan_curve,3547 FAN_CURVE_DEV_MID | FAN_CURVE_PWM_MASK, 2);3548static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point4_pwm, fan_curve,3549 FAN_CURVE_DEV_MID | FAN_CURVE_PWM_MASK, 3);3550static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point5_pwm, fan_curve,3551 FAN_CURVE_DEV_MID | FAN_CURVE_PWM_MASK, 4);3552static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point6_pwm, fan_curve,3553 FAN_CURVE_DEV_MID | FAN_CURVE_PWM_MASK, 5);3554static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point7_pwm, fan_curve,3555 FAN_CURVE_DEV_MID | FAN_CURVE_PWM_MASK, 6);3556static SENSOR_DEVICE_ATTR_2_RW(pwm3_auto_point8_pwm, fan_curve,3557 FAN_CURVE_DEV_MID | FAN_CURVE_PWM_MASK, 7);3558 3559static struct attribute *asus_fan_curve_attr[] = {3560 /* CPU */3561 &sensor_dev_attr_pwm1_enable.dev_attr.attr,3562 &sensor_dev_attr_pwm1_auto_point1_temp.dev_attr.attr,3563 &sensor_dev_attr_pwm1_auto_point2_temp.dev_attr.attr,3564 &sensor_dev_attr_pwm1_auto_point3_temp.dev_attr.attr,3565 &sensor_dev_attr_pwm1_auto_point4_temp.dev_attr.attr,3566 &sensor_dev_attr_pwm1_auto_point5_temp.dev_attr.attr,3567 &sensor_dev_attr_pwm1_auto_point6_temp.dev_attr.attr,3568 &sensor_dev_attr_pwm1_auto_point7_temp.dev_attr.attr,3569 &sensor_dev_attr_pwm1_auto_point8_temp.dev_attr.attr,3570 &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr,3571 &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr,3572 &sensor_dev_attr_pwm1_auto_point3_pwm.dev_attr.attr,3573 &sensor_dev_attr_pwm1_auto_point4_pwm.dev_attr.attr,3574 &sensor_dev_attr_pwm1_auto_point5_pwm.dev_attr.attr,3575 &sensor_dev_attr_pwm1_auto_point6_pwm.dev_attr.attr,3576 &sensor_dev_attr_pwm1_auto_point7_pwm.dev_attr.attr,3577 &sensor_dev_attr_pwm1_auto_point8_pwm.dev_attr.attr,3578 /* GPU */3579 &sensor_dev_attr_pwm2_enable.dev_attr.attr,3580 &sensor_dev_attr_pwm2_auto_point1_temp.dev_attr.attr,3581 &sensor_dev_attr_pwm2_auto_point2_temp.dev_attr.attr,3582 &sensor_dev_attr_pwm2_auto_point3_temp.dev_attr.attr,3583 &sensor_dev_attr_pwm2_auto_point4_temp.dev_attr.attr,3584 &sensor_dev_attr_pwm2_auto_point5_temp.dev_attr.attr,3585 &sensor_dev_attr_pwm2_auto_point6_temp.dev_attr.attr,3586 &sensor_dev_attr_pwm2_auto_point7_temp.dev_attr.attr,3587 &sensor_dev_attr_pwm2_auto_point8_temp.dev_attr.attr,3588 &sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr,3589 &sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr,3590 &sensor_dev_attr_pwm2_auto_point3_pwm.dev_attr.attr,3591 &sensor_dev_attr_pwm2_auto_point4_pwm.dev_attr.attr,3592 &sensor_dev_attr_pwm2_auto_point5_pwm.dev_attr.attr,3593 &sensor_dev_attr_pwm2_auto_point6_pwm.dev_attr.attr,3594 &sensor_dev_attr_pwm2_auto_point7_pwm.dev_attr.attr,3595 &sensor_dev_attr_pwm2_auto_point8_pwm.dev_attr.attr,3596 /* MID */3597 &sensor_dev_attr_pwm3_enable.dev_attr.attr,3598 &sensor_dev_attr_pwm3_auto_point1_temp.dev_attr.attr,3599 &sensor_dev_attr_pwm3_auto_point2_temp.dev_attr.attr,3600 &sensor_dev_attr_pwm3_auto_point3_temp.dev_attr.attr,3601 &sensor_dev_attr_pwm3_auto_point4_temp.dev_attr.attr,3602 &sensor_dev_attr_pwm3_auto_point5_temp.dev_attr.attr,3603 &sensor_dev_attr_pwm3_auto_point6_temp.dev_attr.attr,3604 &sensor_dev_attr_pwm3_auto_point7_temp.dev_attr.attr,3605 &sensor_dev_attr_pwm3_auto_point8_temp.dev_attr.attr,3606 &sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr,3607 &sensor_dev_attr_pwm3_auto_point2_pwm.dev_attr.attr,3608 &sensor_dev_attr_pwm3_auto_point3_pwm.dev_attr.attr,3609 &sensor_dev_attr_pwm3_auto_point4_pwm.dev_attr.attr,3610 &sensor_dev_attr_pwm3_auto_point5_pwm.dev_attr.attr,3611 &sensor_dev_attr_pwm3_auto_point6_pwm.dev_attr.attr,3612 &sensor_dev_attr_pwm3_auto_point7_pwm.dev_attr.attr,3613 &sensor_dev_attr_pwm3_auto_point8_pwm.dev_attr.attr,3614 NULL3615};3616 3617static umode_t asus_fan_curve_is_visible(struct kobject *kobj,3618 struct attribute *attr, int idx)3619{3620 struct device *dev = kobj_to_dev(kobj);3621 struct asus_wmi *asus = dev_get_drvdata(dev->parent);3622 3623 /*3624 * Check the char instead of casting attr as there are two attr types3625 * involved here (attr1 and attr2)3626 */3627 if (asus->cpu_fan_curve_available && attr->name[3] == '1')3628 return 0644;3629 3630 if (asus->gpu_fan_curve_available && attr->name[3] == '2')3631 return 0644;3632 3633 if (asus->mid_fan_curve_available && attr->name[3] == '3')3634 return 0644;3635 3636 return 0;3637}3638 3639static const struct attribute_group asus_fan_curve_attr_group = {3640 .is_visible = asus_fan_curve_is_visible,3641 .attrs = asus_fan_curve_attr,3642};3643__ATTRIBUTE_GROUPS(asus_fan_curve_attr);3644 3645/*3646 * Must be initialised after throttle_thermal_policy_dev is set as3647 * we check the status of throttle_thermal_policy_dev during init.3648 */3649static int asus_wmi_custom_fan_curve_init(struct asus_wmi *asus)3650{3651 struct device *dev = &asus->platform_device->dev;3652 struct device *hwmon;3653 int err;3654 3655 err = fan_curve_check_present(asus, &asus->cpu_fan_curve_available,3656 ASUS_WMI_DEVID_CPU_FAN_CURVE);3657 if (err) {3658 pr_debug("%s, checked 0x%08x, failed: %d\n",3659 __func__, ASUS_WMI_DEVID_CPU_FAN_CURVE, err);3660 return err;3661 }3662 3663 err = fan_curve_check_present(asus, &asus->gpu_fan_curve_available,3664 ASUS_WMI_DEVID_GPU_FAN_CURVE);3665 if (err) {3666 pr_debug("%s, checked 0x%08x, failed: %d\n",3667 __func__, ASUS_WMI_DEVID_GPU_FAN_CURVE, err);3668 return err;3669 }3670 3671 err = fan_curve_check_present(asus, &asus->mid_fan_curve_available,3672 ASUS_WMI_DEVID_MID_FAN_CURVE);3673 if (err) {3674 pr_debug("%s, checked 0x%08x, failed: %d\n",3675 __func__, ASUS_WMI_DEVID_MID_FAN_CURVE, err);3676 return err;3677 }3678 3679 if (!asus->cpu_fan_curve_available3680 && !asus->gpu_fan_curve_available3681 && !asus->mid_fan_curve_available)3682 return 0;3683 3684 hwmon = devm_hwmon_device_register_with_groups(3685 dev, "asus_custom_fan_curve", asus, asus_fan_curve_attr_groups);3686 3687 if (IS_ERR(hwmon)) {3688 dev_err(dev,3689 "Could not register asus_custom_fan_curve device\n");3690 return PTR_ERR(hwmon);3691 }3692 3693 return 0;3694}3695 3696/* Throttle thermal policy ****************************************************/3697static int throttle_thermal_policy_write(struct asus_wmi *asus)3698{3699 u8 value = asus->throttle_thermal_policy_mode;3700 u32 retval;3701 int err;3702 3703 err = asus_wmi_set_devstate(asus->throttle_thermal_policy_dev,3704 value, &retval);3705 3706 sysfs_notify(&asus->platform_device->dev.kobj, NULL,3707 "throttle_thermal_policy");3708 3709 if (err) {3710 pr_warn("Failed to set throttle thermal policy: %d\n", err);3711 return err;3712 }3713 3714 if (retval != 1) {3715 pr_warn("Failed to set throttle thermal policy (retval): 0x%x\n",3716 retval);3717 return -EIO;3718 }3719 3720 /* Must set to disabled if mode is toggled */3721 if (asus->cpu_fan_curve_available)3722 asus->custom_fan_curves[FAN_CURVE_DEV_CPU].enabled = false;3723 if (asus->gpu_fan_curve_available)3724 asus->custom_fan_curves[FAN_CURVE_DEV_GPU].enabled = false;3725 if (asus->mid_fan_curve_available)3726 asus->custom_fan_curves[FAN_CURVE_DEV_MID].enabled = false;3727 3728 return 0;3729}3730 3731static int throttle_thermal_policy_set_default(struct asus_wmi *asus)3732{3733 if (!asus->throttle_thermal_policy_dev)3734 return 0;3735 3736 asus->throttle_thermal_policy_mode = ASUS_THROTTLE_THERMAL_POLICY_DEFAULT;3737 return throttle_thermal_policy_write(asus);3738}3739 3740static int throttle_thermal_policy_switch_next(struct asus_wmi *asus)3741{3742 u8 new_mode = asus->throttle_thermal_policy_mode + 1;3743 int err;3744 3745 if (new_mode > PLATFORM_PROFILE_MAX)3746 new_mode = ASUS_THROTTLE_THERMAL_POLICY_DEFAULT;3747 3748 asus->throttle_thermal_policy_mode = new_mode;3749 err = throttle_thermal_policy_write(asus);3750 if (err)3751 return err;3752 3753 /*3754 * Ensure that platform_profile updates userspace with the change to ensure3755 * that platform_profile and throttle_thermal_policy_mode are in sync.3756 */3757 platform_profile_notify();3758 3759 return 0;3760}3761 3762static ssize_t throttle_thermal_policy_show(struct device *dev,3763 struct device_attribute *attr, char *buf)3764{3765 struct asus_wmi *asus = dev_get_drvdata(dev);3766 u8 mode = asus->throttle_thermal_policy_mode;3767 3768 return sysfs_emit(buf, "%d\n", mode);3769}3770 3771static ssize_t throttle_thermal_policy_store(struct device *dev,3772 struct device_attribute *attr,3773 const char *buf, size_t count)3774{3775 struct asus_wmi *asus = dev_get_drvdata(dev);3776 u8 new_mode;3777 int result;3778 int err;3779 3780 result = kstrtou8(buf, 10, &new_mode);3781 if (result < 0)3782 return result;3783 3784 if (new_mode > PLATFORM_PROFILE_MAX)3785 return -EINVAL;3786 3787 asus->throttle_thermal_policy_mode = new_mode;3788 err = throttle_thermal_policy_write(asus);3789 if (err)3790 return err;3791 3792 /*3793 * Ensure that platform_profile updates userspace with the change to ensure3794 * that platform_profile and throttle_thermal_policy_mode are in sync.3795 */3796 platform_profile_notify();3797 3798 return count;3799}3800 3801/*3802 * Throttle thermal policy: 0 - default, 1 - overboost, 2 - silent3803 */3804static DEVICE_ATTR_RW(throttle_thermal_policy);3805 3806/* Platform profile ***********************************************************/3807static int asus_wmi_platform_profile_to_vivo(struct asus_wmi *asus, int mode)3808{3809 bool vivo;3810 3811 vivo = asus->throttle_thermal_policy_dev == ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO;3812 3813 if (vivo) {3814 switch (mode) {3815 case ASUS_THROTTLE_THERMAL_POLICY_DEFAULT:3816 return ASUS_THROTTLE_THERMAL_POLICY_DEFAULT_VIVO;3817 case ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST:3818 return ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST_VIVO;3819 case ASUS_THROTTLE_THERMAL_POLICY_SILENT:3820 return ASUS_THROTTLE_THERMAL_POLICY_SILENT_VIVO;3821 }3822 }3823 3824 return mode;3825}3826 3827static int asus_wmi_platform_profile_mode_from_vivo(struct asus_wmi *asus, int mode)3828{3829 bool vivo;3830 3831 vivo = asus->throttle_thermal_policy_dev == ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO;3832 3833 if (vivo) {3834 switch (mode) {3835 case ASUS_THROTTLE_THERMAL_POLICY_DEFAULT_VIVO:3836 return ASUS_THROTTLE_THERMAL_POLICY_DEFAULT;3837 case ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST_VIVO:3838 return ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST;3839 case ASUS_THROTTLE_THERMAL_POLICY_SILENT_VIVO:3840 return ASUS_THROTTLE_THERMAL_POLICY_SILENT;3841 }3842 }3843 3844 return mode;3845}3846 3847static int asus_wmi_platform_profile_get(struct platform_profile_handler *pprof,3848 enum platform_profile_option *profile)3849{3850 struct asus_wmi *asus;3851 int tp;3852 3853 asus = container_of(pprof, struct asus_wmi, platform_profile_handler);3854 tp = asus->throttle_thermal_policy_mode;3855 3856 switch (asus_wmi_platform_profile_mode_from_vivo(asus, tp)) {3857 case ASUS_THROTTLE_THERMAL_POLICY_DEFAULT:3858 *profile = PLATFORM_PROFILE_BALANCED;3859 break;3860 case ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST:3861 *profile = PLATFORM_PROFILE_PERFORMANCE;3862 break;3863 case ASUS_THROTTLE_THERMAL_POLICY_SILENT:3864 *profile = PLATFORM_PROFILE_QUIET;3865 break;3866 default:3867 return -EINVAL;3868 }3869 3870 return 0;3871}3872 3873static int asus_wmi_platform_profile_set(struct platform_profile_handler *pprof,3874 enum platform_profile_option profile)3875{3876 struct asus_wmi *asus;3877 int tp;3878 3879 asus = container_of(pprof, struct asus_wmi, platform_profile_handler);3880 3881 switch (profile) {3882 case PLATFORM_PROFILE_PERFORMANCE:3883 tp = ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST;3884 break;3885 case PLATFORM_PROFILE_BALANCED:3886 tp = ASUS_THROTTLE_THERMAL_POLICY_DEFAULT;3887 break;3888 case PLATFORM_PROFILE_QUIET:3889 tp = ASUS_THROTTLE_THERMAL_POLICY_SILENT;3890 break;3891 default:3892 return -EOPNOTSUPP;3893 }3894 3895 asus->throttle_thermal_policy_mode = asus_wmi_platform_profile_to_vivo(asus, tp);3896 return throttle_thermal_policy_write(asus);3897}3898 3899static int platform_profile_setup(struct asus_wmi *asus)3900{3901 struct device *dev = &asus->platform_device->dev;3902 int err;3903 3904 /*3905 * Not an error if a component platform_profile relies on is unavailable3906 * so early return, skipping the setup of platform_profile.3907 */3908 if (!asus->throttle_thermal_policy_dev)3909 return 0;3910 3911 /*3912 * We need to set the default thermal profile during probe or otherwise3913 * the system will often remain in silent mode, causing low performance.3914 */3915 err = throttle_thermal_policy_set_default(asus);3916 if (err < 0) {3917 pr_warn("Failed to set default thermal profile\n");3918 return err;3919 }3920 3921 dev_info(dev, "Using throttle_thermal_policy for platform_profile support\n");3922 3923 asus->platform_profile_handler.profile_get = asus_wmi_platform_profile_get;3924 asus->platform_profile_handler.profile_set = asus_wmi_platform_profile_set;3925 3926 set_bit(PLATFORM_PROFILE_QUIET, asus->platform_profile_handler.choices);3927 set_bit(PLATFORM_PROFILE_BALANCED,3928 asus->platform_profile_handler.choices);3929 set_bit(PLATFORM_PROFILE_PERFORMANCE,3930 asus->platform_profile_handler.choices);3931 3932 err = platform_profile_register(&asus->platform_profile_handler);3933 if (err == -EEXIST) {3934 pr_warn("%s, a platform_profile handler is already registered\n", __func__);3935 return 0;3936 } else if (err) {3937 pr_err("%s, failed at platform_profile_register: %d\n", __func__, err);3938 return err;3939 }3940 3941 asus->platform_profile_support = true;3942 return 0;3943}3944 3945/* Backlight ******************************************************************/3946 3947static int read_backlight_power(struct asus_wmi *asus)3948{3949 int ret;3950 3951 if (asus->driver->quirks->store_backlight_power)3952 ret = !asus->driver->panel_power;3953 else3954 ret = asus_wmi_get_devstate_simple(asus,3955 ASUS_WMI_DEVID_BACKLIGHT);3956 3957 if (ret < 0)3958 return ret;3959 3960 return ret ? BACKLIGHT_POWER_ON : BACKLIGHT_POWER_OFF;3961}3962 3963static int read_brightness_max(struct asus_wmi *asus)3964{3965 u32 retval;3966 int err;3967 3968 err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_BRIGHTNESS, &retval);3969 if (err < 0)3970 return err;3971 3972 retval = retval & ASUS_WMI_DSTS_MAX_BRIGTH_MASK;3973 retval >>= 8;3974 3975 if (!retval)3976 return -ENODEV;3977 3978 return retval;3979}3980 3981static int read_brightness(struct backlight_device *bd)3982{3983 struct asus_wmi *asus = bl_get_data(bd);3984 u32 retval;3985 int err;3986 3987 err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_BRIGHTNESS, &retval);3988 if (err < 0)3989 return err;3990 3991 return retval & ASUS_WMI_DSTS_BRIGHTNESS_MASK;3992}3993 3994static u32 get_scalar_command(struct backlight_device *bd)3995{3996 struct asus_wmi *asus = bl_get_data(bd);3997 u32 ctrl_param = 0;3998 3999 if ((asus->driver->brightness < bd->props.brightness) ||4000 bd->props.brightness == bd->props.max_brightness)4001 ctrl_param = 0x00008001;4002 else if ((asus->driver->brightness > bd->props.brightness) ||4003 bd->props.brightness == 0)4004 ctrl_param = 0x00008000;4005 4006 asus->driver->brightness = bd->props.brightness;4007 4008 return ctrl_param;4009}4010 4011static int update_bl_status(struct backlight_device *bd)4012{4013 struct asus_wmi *asus = bl_get_data(bd);4014 u32 ctrl_param;4015 int power, err = 0;4016 4017 power = read_backlight_power(asus);4018 if (power != -ENODEV && bd->props.power != power) {4019 ctrl_param = !!(bd->props.power == BACKLIGHT_POWER_ON);4020 err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BACKLIGHT,4021 ctrl_param, NULL);4022 if (asus->driver->quirks->store_backlight_power)4023 asus->driver->panel_power = bd->props.power;4024 4025 /* When using scalar brightness, updating the brightness4026 * will mess with the backlight power */4027 if (asus->driver->quirks->scalar_panel_brightness)4028 return err;4029 }4030 4031 if (asus->driver->quirks->scalar_panel_brightness)4032 ctrl_param = get_scalar_command(bd);4033 else4034 ctrl_param = bd->props.brightness;4035 4036 err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BRIGHTNESS,4037 ctrl_param, NULL);4038 4039 return err;4040}4041 4042static const struct backlight_ops asus_wmi_bl_ops = {4043 .get_brightness = read_brightness,4044 .update_status = update_bl_status,4045};4046 4047static int asus_wmi_backlight_notify(struct asus_wmi *asus, int code)4048{4049 struct backlight_device *bd = asus->backlight_device;4050 int old = bd->props.brightness;4051 int new = old;4052 4053 if (code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNUP_MAX)4054 new = code - NOTIFY_BRNUP_MIN + 1;4055 else if (code >= NOTIFY_BRNDOWN_MIN && code <= NOTIFY_BRNDOWN_MAX)4056 new = code - NOTIFY_BRNDOWN_MIN;4057 4058 bd->props.brightness = new;4059 backlight_update_status(bd);4060 backlight_force_update(bd, BACKLIGHT_UPDATE_HOTKEY);4061 4062 return old;4063}4064 4065static int asus_wmi_backlight_init(struct asus_wmi *asus)4066{4067 struct backlight_device *bd;4068 struct backlight_properties props;4069 int max;4070 int power;4071 4072 max = read_brightness_max(asus);4073 if (max < 0)4074 return max;4075 4076 power = read_backlight_power(asus);4077 if (power == -ENODEV)4078 power = BACKLIGHT_POWER_ON;4079 else if (power < 0)4080 return power;4081 4082 memset(&props, 0, sizeof(struct backlight_properties));4083 props.type = BACKLIGHT_PLATFORM;4084 props.max_brightness = max;4085 bd = backlight_device_register(asus->driver->name,4086 &asus->platform_device->dev, asus,4087 &asus_wmi_bl_ops, &props);4088 if (IS_ERR(bd)) {4089 pr_err("Could not register backlight device\n");4090 return PTR_ERR(bd);4091 }4092 4093 asus->backlight_device = bd;4094 4095 if (asus->driver->quirks->store_backlight_power)4096 asus->driver->panel_power = power;4097 4098 bd->props.brightness = read_brightness(bd);4099 bd->props.power = power;4100 backlight_update_status(bd);4101 4102 asus->driver->brightness = bd->props.brightness;4103 4104 return 0;4105}4106 4107static void asus_wmi_backlight_exit(struct asus_wmi *asus)4108{4109 backlight_device_unregister(asus->backlight_device);4110 4111 asus->backlight_device = NULL;4112}4113 4114static int is_display_toggle(int code)4115{4116 /* display toggle keys */4117 if ((code >= 0x61 && code <= 0x67) ||4118 (code >= 0x8c && code <= 0x93) ||4119 (code >= 0xa0 && code <= 0xa7) ||4120 (code >= 0xd0 && code <= 0xd5))4121 return 1;4122 4123 return 0;4124}4125 4126/* Screenpad backlight *******************************************************/4127 4128static int read_screenpad_backlight_power(struct asus_wmi *asus)4129{4130 int ret;4131 4132 ret = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_SCREENPAD_POWER);4133 if (ret < 0)4134 return ret;4135 /* 1 == powered */4136 return ret ? BACKLIGHT_POWER_ON : BACKLIGHT_POWER_OFF;4137}4138 4139static int read_screenpad_brightness(struct backlight_device *bd)4140{4141 struct asus_wmi *asus = bl_get_data(bd);4142 u32 retval;4143 int err;4144 4145 err = read_screenpad_backlight_power(asus);4146 if (err < 0)4147 return err;4148 /* The device brightness can only be read if powered, so return stored */4149 if (err == BACKLIGHT_POWER_OFF)4150 return asus->driver->screenpad_brightness - ASUS_SCREENPAD_BRIGHT_MIN;4151 4152 err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_SCREENPAD_LIGHT, &retval);4153 if (err < 0)4154 return err;4155 4156 return (retval & ASUS_WMI_DSTS_BRIGHTNESS_MASK) - ASUS_SCREENPAD_BRIGHT_MIN;4157}4158 4159static int update_screenpad_bl_status(struct backlight_device *bd)4160{4161 struct asus_wmi *asus = bl_get_data(bd);4162 int power, err = 0;4163 u32 ctrl_param;4164 4165 power = read_screenpad_backlight_power(asus);4166 if (power < 0)4167 return power;4168 4169 if (bd->props.power != power) {4170 if (power != BACKLIGHT_POWER_ON) {4171 /* Only brightness > 0 can power it back on */4172 ctrl_param = asus->driver->screenpad_brightness - ASUS_SCREENPAD_BRIGHT_MIN;4173 err = asus_wmi_set_devstate(ASUS_WMI_DEVID_SCREENPAD_LIGHT,4174 ctrl_param, NULL);4175 } else {4176 err = asus_wmi_set_devstate(ASUS_WMI_DEVID_SCREENPAD_POWER, 0, NULL);4177 }4178 } else if (power == BACKLIGHT_POWER_ON) {4179 /* Only set brightness if powered on or we get invalid/unsync state */4180 ctrl_param = bd->props.brightness + ASUS_SCREENPAD_BRIGHT_MIN;4181 err = asus_wmi_set_devstate(ASUS_WMI_DEVID_SCREENPAD_LIGHT, ctrl_param, NULL);4182 }4183 4184 /* Ensure brightness is stored to turn back on with */4185 if (err == 0)4186 asus->driver->screenpad_brightness = bd->props.brightness + ASUS_SCREENPAD_BRIGHT_MIN;4187 4188 return err;4189}4190 4191static const struct backlight_ops asus_screenpad_bl_ops = {4192 .get_brightness = read_screenpad_brightness,4193 .update_status = update_screenpad_bl_status,4194 .options = BL_CORE_SUSPENDRESUME,4195};4196 4197static int asus_screenpad_init(struct asus_wmi *asus)4198{4199 struct backlight_device *bd;4200 struct backlight_properties props;4201 int err, power;4202 int brightness = 0;4203 4204 power = read_screenpad_backlight_power(asus);4205 if (power < 0)4206 return power;4207 4208 if (power != BACKLIGHT_POWER_OFF) {4209 err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_SCREENPAD_LIGHT, &brightness);4210 if (err < 0)4211 return err;4212 }4213 /* default to an acceptable min brightness on boot if too low */4214 if (brightness < ASUS_SCREENPAD_BRIGHT_MIN)4215 brightness = ASUS_SCREENPAD_BRIGHT_DEFAULT;4216 4217 memset(&props, 0, sizeof(struct backlight_properties));4218 props.type = BACKLIGHT_RAW; /* ensure this bd is last to be picked */4219 props.max_brightness = ASUS_SCREENPAD_BRIGHT_MAX - ASUS_SCREENPAD_BRIGHT_MIN;4220 bd = backlight_device_register("asus_screenpad",4221 &asus->platform_device->dev, asus,4222 &asus_screenpad_bl_ops, &props);4223 if (IS_ERR(bd)) {4224 pr_err("Could not register backlight device\n");4225 return PTR_ERR(bd);4226 }4227 4228 asus->screenpad_backlight_device = bd;4229 asus->driver->screenpad_brightness = brightness;4230 bd->props.brightness = brightness - ASUS_SCREENPAD_BRIGHT_MIN;4231 bd->props.power = power;4232 backlight_update_status(bd);4233 4234 return 0;4235}4236 4237static void asus_screenpad_exit(struct asus_wmi *asus)4238{4239 backlight_device_unregister(asus->screenpad_backlight_device);4240 4241 asus->screenpad_backlight_device = NULL;4242}4243 4244/* Fn-lock ********************************************************************/4245 4246static bool asus_wmi_has_fnlock_key(struct asus_wmi *asus)4247{4248 u32 result;4249 4250 asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_FNLOCK, &result);4251 4252 return (result & ASUS_WMI_DSTS_PRESENCE_BIT) &&4253 !(result & ASUS_WMI_FNLOCK_BIOS_DISABLED);4254}4255 4256static void asus_wmi_fnlock_update(struct asus_wmi *asus)4257{4258 int mode = asus->fnlock_locked;4259 4260 asus_wmi_set_devstate(ASUS_WMI_DEVID_FNLOCK, mode, NULL);4261}4262 4263/* WMI events *****************************************************************/4264 4265static int asus_wmi_get_event_code(union acpi_object *obj)4266{4267 int code;4268 4269 if (obj && obj->type == ACPI_TYPE_INTEGER)4270 code = (int)(obj->integer.value & WMI_EVENT_MASK);4271 else4272 code = -EIO;4273 4274 return code;4275}4276 4277static void asus_wmi_handle_event_code(int code, struct asus_wmi *asus)4278{4279 unsigned int key_value = 1;4280 bool autorelease = 1;4281 4282 if (asus->driver->key_filter) {4283 asus->driver->key_filter(asus->driver, &code, &key_value,4284 &autorelease);4285 if (code == ASUS_WMI_KEY_IGNORE)4286 return;4287 }4288 4289 if (acpi_video_get_backlight_type() == acpi_backlight_vendor &&4290 code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNDOWN_MAX) {4291 asus_wmi_backlight_notify(asus, code);4292 return;4293 }4294 4295 if (code == NOTIFY_KBD_BRTUP) {4296 kbd_led_set_by_kbd(asus, asus->kbd_led_wk + 1);4297 return;4298 }4299 if (code == NOTIFY_KBD_BRTDWN) {4300 kbd_led_set_by_kbd(asus, asus->kbd_led_wk - 1);4301 return;4302 }4303 if (code == NOTIFY_KBD_BRTTOGGLE) {4304 if (asus->kbd_led_wk == asus->kbd_led.max_brightness)4305 kbd_led_set_by_kbd(asus, 0);4306 else4307 kbd_led_set_by_kbd(asus, asus->kbd_led_wk + 1);4308 return;4309 }4310 4311 if (code == NOTIFY_FNLOCK_TOGGLE) {4312 asus->fnlock_locked = !asus->fnlock_locked;4313 asus_wmi_fnlock_update(asus);4314 return;4315 }4316 4317 if (code == asus->tablet_switch_event_code) {4318 asus_wmi_tablet_mode_get_state(asus);4319 return;4320 }4321 4322 if (code == NOTIFY_KBD_FBM || code == NOTIFY_KBD_TTP) {4323 if (asus->fan_boost_mode_available)4324 fan_boost_mode_switch_next(asus);4325 if (asus->throttle_thermal_policy_dev)4326 throttle_thermal_policy_switch_next(asus);4327 return;4328 4329 }4330 4331 if (is_display_toggle(code) && asus->driver->quirks->no_display_toggle)4332 return;4333 4334 if (!sparse_keymap_report_event(asus->inputdev, code,4335 key_value, autorelease))4336 pr_info("Unknown key code 0x%x\n", code);4337}4338 4339static void asus_wmi_notify(union acpi_object *obj, void *context)4340{4341 struct asus_wmi *asus = context;4342 int code = asus_wmi_get_event_code(obj);4343 4344 if (code < 0) {4345 pr_warn("Failed to get notify code: %d\n", code);4346 return;4347 }4348 4349 asus_wmi_handle_event_code(code, asus);4350}4351 4352/* Sysfs **********************************************************************/4353 4354static ssize_t store_sys_wmi(struct asus_wmi *asus, int devid,4355 const char *buf, size_t count)4356{4357 u32 retval;4358 int err, value;4359 4360 value = asus_wmi_get_devstate_simple(asus, devid);4361 if (value < 0)4362 return value;4363 4364 err = kstrtoint(buf, 0, &value);4365 if (err)4366 return err;4367 4368 err = asus_wmi_set_devstate(devid, value, &retval);4369 if (err < 0)4370 return err;4371 4372 return count;4373}4374 4375static ssize_t show_sys_wmi(struct asus_wmi *asus, int devid, char *buf)4376{4377 int value = asus_wmi_get_devstate_simple(asus, devid);4378 4379 if (value < 0)4380 return value;4381 4382 return sysfs_emit(buf, "%d\n", value);4383}4384 4385#define ASUS_WMI_CREATE_DEVICE_ATTR(_name, _mode, _cm) \4386 static ssize_t show_##_name(struct device *dev, \4387 struct device_attribute *attr, \4388 char *buf) \4389 { \4390 struct asus_wmi *asus = dev_get_drvdata(dev); \4391 \4392 return show_sys_wmi(asus, _cm, buf); \4393 } \4394 static ssize_t store_##_name(struct device *dev, \4395 struct device_attribute *attr, \4396 const char *buf, size_t count) \4397 { \4398 struct asus_wmi *asus = dev_get_drvdata(dev); \4399 \4400 return store_sys_wmi(asus, _cm, buf, count); \4401 } \4402 static struct device_attribute dev_attr_##_name = { \4403 .attr = { \4404 .name = __stringify(_name), \4405 .mode = _mode }, \4406 .show = show_##_name, \4407 .store = store_##_name, \4408 }4409 4410ASUS_WMI_CREATE_DEVICE_ATTR(touchpad, 0644, ASUS_WMI_DEVID_TOUCHPAD);4411ASUS_WMI_CREATE_DEVICE_ATTR(camera, 0644, ASUS_WMI_DEVID_CAMERA);4412ASUS_WMI_CREATE_DEVICE_ATTR(cardr, 0644, ASUS_WMI_DEVID_CARDREADER);4413ASUS_WMI_CREATE_DEVICE_ATTR(lid_resume, 0644, ASUS_WMI_DEVID_LID_RESUME);4414ASUS_WMI_CREATE_DEVICE_ATTR(als_enable, 0644, ASUS_WMI_DEVID_ALS_ENABLE);4415 4416static ssize_t cpufv_store(struct device *dev, struct device_attribute *attr,4417 const char *buf, size_t count)4418{4419 int value, rv;4420 4421 rv = kstrtoint(buf, 0, &value);4422 if (rv)4423 return rv;4424 4425 if (value < 0 || value > 2)4426 return -EINVAL;4427 4428 rv = asus_wmi_evaluate_method(ASUS_WMI_METHODID_CFVS, value, 0, NULL);4429 if (rv < 0)4430 return rv;4431 4432 return count;4433}4434 4435static DEVICE_ATTR_WO(cpufv);4436 4437static struct attribute *platform_attributes[] = {4438 &dev_attr_cpufv.attr,4439 &dev_attr_camera.attr,4440 &dev_attr_cardr.attr,4441 &dev_attr_touchpad.attr,4442 &dev_attr_charge_mode.attr,4443 &dev_attr_egpu_enable.attr,4444 &dev_attr_egpu_connected.attr,4445 &dev_attr_dgpu_disable.attr,4446 &dev_attr_gpu_mux_mode.attr,4447 &dev_attr_lid_resume.attr,4448 &dev_attr_als_enable.attr,4449 &dev_attr_fan_boost_mode.attr,4450 &dev_attr_throttle_thermal_policy.attr,4451 &dev_attr_ppt_pl2_sppt.attr,4452 &dev_attr_ppt_pl1_spl.attr,4453 &dev_attr_ppt_fppt.attr,4454 &dev_attr_ppt_apu_sppt.attr,4455 &dev_attr_ppt_platform_sppt.attr,4456 &dev_attr_nv_dynamic_boost.attr,4457 &dev_attr_nv_temp_target.attr,4458 &dev_attr_mcu_powersave.attr,4459 &dev_attr_boot_sound.attr,4460 &dev_attr_panel_od.attr,4461 &dev_attr_mini_led_mode.attr,4462 &dev_attr_available_mini_led_mode.attr,4463 NULL4464};4465 4466static umode_t asus_sysfs_is_visible(struct kobject *kobj,4467 struct attribute *attr, int idx)4468{4469 struct device *dev = kobj_to_dev(kobj);4470 struct asus_wmi *asus = dev_get_drvdata(dev);4471 bool ok = true;4472 int devid = -1;4473 4474 if (attr == &dev_attr_camera.attr)4475 devid = ASUS_WMI_DEVID_CAMERA;4476 else if (attr == &dev_attr_cardr.attr)4477 devid = ASUS_WMI_DEVID_CARDREADER;4478 else if (attr == &dev_attr_touchpad.attr)4479 devid = ASUS_WMI_DEVID_TOUCHPAD;4480 else if (attr == &dev_attr_lid_resume.attr)4481 devid = ASUS_WMI_DEVID_LID_RESUME;4482 else if (attr == &dev_attr_als_enable.attr)4483 devid = ASUS_WMI_DEVID_ALS_ENABLE;4484 else if (attr == &dev_attr_charge_mode.attr)4485 devid = ASUS_WMI_DEVID_CHARGE_MODE;4486 else if (attr == &dev_attr_egpu_enable.attr)4487 ok = asus->egpu_enable_available;4488 else if (attr == &dev_attr_egpu_connected.attr)4489 devid = ASUS_WMI_DEVID_EGPU_CONNECTED;4490 else if (attr == &dev_attr_dgpu_disable.attr)4491 ok = asus->dgpu_disable_available;4492 else if (attr == &dev_attr_gpu_mux_mode.attr)4493 ok = asus->gpu_mux_dev != 0;4494 else if (attr == &dev_attr_fan_boost_mode.attr)4495 ok = asus->fan_boost_mode_available;4496 else if (attr == &dev_attr_throttle_thermal_policy.attr)4497 ok = asus->throttle_thermal_policy_dev != 0;4498 else if (attr == &dev_attr_ppt_pl2_sppt.attr)4499 devid = ASUS_WMI_DEVID_PPT_PL2_SPPT;4500 else if (attr == &dev_attr_ppt_pl1_spl.attr)4501 devid = ASUS_WMI_DEVID_PPT_PL1_SPL;4502 else if (attr == &dev_attr_ppt_fppt.attr)4503 devid = ASUS_WMI_DEVID_PPT_FPPT;4504 else if (attr == &dev_attr_ppt_apu_sppt.attr)4505 devid = ASUS_WMI_DEVID_PPT_APU_SPPT;4506 else if (attr == &dev_attr_ppt_platform_sppt.attr)4507 devid = ASUS_WMI_DEVID_PPT_PLAT_SPPT;4508 else if (attr == &dev_attr_nv_dynamic_boost.attr)4509 devid = ASUS_WMI_DEVID_NV_DYN_BOOST;4510 else if (attr == &dev_attr_nv_temp_target.attr)4511 devid = ASUS_WMI_DEVID_NV_THERM_TARGET;4512 else if (attr == &dev_attr_mcu_powersave.attr)4513 devid = ASUS_WMI_DEVID_MCU_POWERSAVE;4514 else if (attr == &dev_attr_boot_sound.attr)4515 devid = ASUS_WMI_DEVID_BOOT_SOUND;4516 else if (attr == &dev_attr_panel_od.attr)4517 devid = ASUS_WMI_DEVID_PANEL_OD;4518 else if (attr == &dev_attr_mini_led_mode.attr)4519 ok = asus->mini_led_dev_id != 0;4520 else if (attr == &dev_attr_available_mini_led_mode.attr)4521 ok = asus->mini_led_dev_id != 0;4522 4523 if (devid != -1) {4524 ok = !(asus_wmi_get_devstate_simple(asus, devid) < 0);4525 pr_debug("%s called 0x%08x, ok: %x\n", __func__, devid, ok);4526 }4527 4528 return ok ? attr->mode : 0;4529}4530 4531static const struct attribute_group platform_attribute_group = {4532 .is_visible = asus_sysfs_is_visible,4533 .attrs = platform_attributes4534};4535 4536static void asus_wmi_sysfs_exit(struct platform_device *device)4537{4538 sysfs_remove_group(&device->dev.kobj, &platform_attribute_group);4539}4540 4541static int asus_wmi_sysfs_init(struct platform_device *device)4542{4543 return sysfs_create_group(&device->dev.kobj, &platform_attribute_group);4544}4545 4546/* Platform device ************************************************************/4547 4548static int asus_wmi_platform_init(struct asus_wmi *asus)4549{4550 struct device *dev = &asus->platform_device->dev;4551 char *wmi_uid;4552 int rv;4553 4554 /* INIT enable hotkeys on some models */4555 if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_INIT, 0, 0, &rv))4556 pr_info("Initialization: %#x\n", rv);4557 4558 /* We don't know yet what to do with this version... */4559 if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_SPEC, 0, 0x9, &rv)) {4560 pr_info("BIOS WMI version: %d.%d\n", rv >> 16, rv & 0xFF);4561 asus->spec = rv;4562 }4563 4564 /*4565 * The SFUN method probably allows the original driver to get the list4566 * of features supported by a given model. For now, 0x0100 or 0x08004567 * bit signifies that the laptop is equipped with a Wi-Fi MiniPCI card.4568 * The significance of others is yet to be found.4569 */4570 if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_SFUN, 0, 0, &rv)) {4571 pr_info("SFUN value: %#x\n", rv);4572 asus->sfun = rv;4573 }4574 4575 /*4576 * Eee PC and Notebooks seems to have different method_id for DSTS,4577 * but it may also be related to the BIOS's SPEC.4578 * Note, on most Eeepc, there is no way to check if a method exist4579 * or note, while on notebooks, they returns 0xFFFFFFFE on failure,4580 * but once again, SPEC may probably be used for that kind of things.4581 *4582 * Additionally at least TUF Gaming series laptops return nothing for4583 * unknown methods, so the detection in this way is not possible.4584 *4585 * There is strong indication that only ACPI WMI devices that have _UID4586 * equal to "ASUSWMI" use DCTS whereas those with "ATK" use DSTS.4587 */4588 wmi_uid = wmi_get_acpi_device_uid(ASUS_WMI_MGMT_GUID);4589 if (!wmi_uid)4590 return -ENODEV;4591 4592 if (!strcmp(wmi_uid, ASUS_ACPI_UID_ASUSWMI)) {4593 dev_info(dev, "Detected ASUSWMI, use DCTS\n");4594 asus->dsts_id = ASUS_WMI_METHODID_DCTS;4595 } else {4596 dev_info(dev, "Detected %s, not ASUSWMI, use DSTS\n", wmi_uid);4597 asus->dsts_id = ASUS_WMI_METHODID_DSTS;4598 }4599 4600 /* CWAP allow to define the behavior of the Fn+F2 key,4601 * this method doesn't seems to be present on Eee PCs */4602 if (asus->driver->quirks->wapf >= 0)4603 asus_wmi_set_devstate(ASUS_WMI_DEVID_CWAP,4604 asus->driver->quirks->wapf, NULL);4605 4606 return 0;4607}4608 4609/* debugfs ********************************************************************/4610 4611struct asus_wmi_debugfs_node {4612 struct asus_wmi *asus;4613 char *name;4614 int (*show) (struct seq_file *m, void *data);4615};4616 4617static int show_dsts(struct seq_file *m, void *data)4618{4619 struct asus_wmi *asus = m->private;4620 int err;4621 u32 retval = -1;4622 4623 err = asus_wmi_get_devstate(asus, asus->debug.dev_id, &retval);4624 if (err < 0)4625 return err;4626 4627 seq_printf(m, "DSTS(%#x) = %#x\n", asus->debug.dev_id, retval);4628 4629 return 0;4630}4631 4632static int show_devs(struct seq_file *m, void *data)4633{4634 struct asus_wmi *asus = m->private;4635 int err;4636 u32 retval = -1;4637 4638 err = asus_wmi_set_devstate(asus->debug.dev_id, asus->debug.ctrl_param,4639 &retval);4640 if (err < 0)4641 return err;4642 4643 seq_printf(m, "DEVS(%#x, %#x) = %#x\n", asus->debug.dev_id,4644 asus->debug.ctrl_param, retval);4645 4646 return 0;4647}4648 4649static int show_call(struct seq_file *m, void *data)4650{4651 struct asus_wmi *asus = m->private;4652 struct bios_args args = {4653 .arg0 = asus->debug.dev_id,4654 .arg1 = asus->debug.ctrl_param,4655 };4656 struct acpi_buffer input = { (acpi_size) sizeof(args), &args };4657 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };4658 union acpi_object *obj;4659 acpi_status status;4660 4661 status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID,4662 0, asus->debug.method_id,4663 &input, &output);4664 4665 if (ACPI_FAILURE(status))4666 return -EIO;4667 4668 obj = (union acpi_object *)output.pointer;4669 if (obj && obj->type == ACPI_TYPE_INTEGER)4670 seq_printf(m, "%#x(%#x, %#x) = %#x\n", asus->debug.method_id,4671 asus->debug.dev_id, asus->debug.ctrl_param,4672 (u32) obj->integer.value);4673 else4674 seq_printf(m, "%#x(%#x, %#x) = t:%d\n", asus->debug.method_id,4675 asus->debug.dev_id, asus->debug.ctrl_param,4676 obj ? obj->type : -1);4677 4678 kfree(obj);4679 4680 return 0;4681}4682 4683static struct asus_wmi_debugfs_node asus_wmi_debug_files[] = {4684 {NULL, "devs", show_devs},4685 {NULL, "dsts", show_dsts},4686 {NULL, "call", show_call},4687};4688 4689static int asus_wmi_debugfs_open(struct inode *inode, struct file *file)4690{4691 struct asus_wmi_debugfs_node *node = inode->i_private;4692 4693 return single_open(file, node->show, node->asus);4694}4695 4696static const struct file_operations asus_wmi_debugfs_io_ops = {4697 .owner = THIS_MODULE,4698 .open = asus_wmi_debugfs_open,4699 .read = seq_read,4700 .llseek = seq_lseek,4701 .release = single_release,4702};4703 4704static void asus_wmi_debugfs_exit(struct asus_wmi *asus)4705{4706 debugfs_remove_recursive(asus->debug.root);4707}4708 4709static void asus_wmi_debugfs_init(struct asus_wmi *asus)4710{4711 int i;4712 4713 asus->debug.root = debugfs_create_dir(asus->driver->name, NULL);4714 4715 debugfs_create_x32("method_id", S_IRUGO | S_IWUSR, asus->debug.root,4716 &asus->debug.method_id);4717 4718 debugfs_create_x32("dev_id", S_IRUGO | S_IWUSR, asus->debug.root,4719 &asus->debug.dev_id);4720 4721 debugfs_create_x32("ctrl_param", S_IRUGO | S_IWUSR, asus->debug.root,4722 &asus->debug.ctrl_param);4723 4724 for (i = 0; i < ARRAY_SIZE(asus_wmi_debug_files); i++) {4725 struct asus_wmi_debugfs_node *node = &asus_wmi_debug_files[i];4726 4727 node->asus = asus;4728 debugfs_create_file(node->name, S_IFREG | S_IRUGO,4729 asus->debug.root, node,4730 &asus_wmi_debugfs_io_ops);4731 }4732}4733 4734/* Init / exit ****************************************************************/4735 4736static int asus_wmi_add(struct platform_device *pdev)4737{4738 struct platform_driver *pdrv = to_platform_driver(pdev->dev.driver);4739 struct asus_wmi_driver *wdrv = to_asus_wmi_driver(pdrv);4740 struct asus_wmi *asus;4741 acpi_status status;4742 int err;4743 u32 result;4744 4745 asus = kzalloc(sizeof(struct asus_wmi), GFP_KERNEL);4746 if (!asus)4747 return -ENOMEM;4748 4749 asus->driver = wdrv;4750 asus->platform_device = pdev;4751 wdrv->platform_device = pdev;4752 platform_set_drvdata(asus->platform_device, asus);4753 4754 if (wdrv->detect_quirks)4755 wdrv->detect_quirks(asus->driver);4756 4757 err = asus_wmi_platform_init(asus);4758 if (err)4759 goto fail_platform;4760 4761 /* ensure defaults for tunables */4762 asus->ppt_pl2_sppt = 5;4763 asus->ppt_pl1_spl = 5;4764 asus->ppt_apu_sppt = 5;4765 asus->ppt_platform_sppt = 5;4766 asus->ppt_fppt = 5;4767 asus->nv_dynamic_boost = 5;4768 asus->nv_temp_target = 75;4769 4770 asus->egpu_enable_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_EGPU);4771 asus->dgpu_disable_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_DGPU);4772 asus->kbd_rgb_state_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_STATE);4773 asus->ally_mcu_usb_switch = acpi_has_method(NULL, ASUS_USB0_PWR_EC0_CSEE)4774 && dmi_check_system(asus_ally_mcu_quirk);4775 4776 if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_MINI_LED_MODE))4777 asus->mini_led_dev_id = ASUS_WMI_DEVID_MINI_LED_MODE;4778 else if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_MINI_LED_MODE2))4779 asus->mini_led_dev_id = ASUS_WMI_DEVID_MINI_LED_MODE2;4780 4781 if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_GPU_MUX))4782 asus->gpu_mux_dev = ASUS_WMI_DEVID_GPU_MUX;4783 else if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_GPU_MUX_VIVO))4784 asus->gpu_mux_dev = ASUS_WMI_DEVID_GPU_MUX_VIVO;4785 4786 if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_MODE))4787 asus->kbd_rgb_dev = ASUS_WMI_DEVID_TUF_RGB_MODE;4788 else if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_MODE2))4789 asus->kbd_rgb_dev = ASUS_WMI_DEVID_TUF_RGB_MODE2;4790 4791 if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY))4792 asus->throttle_thermal_policy_dev = ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY;4793 else if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO))4794 asus->throttle_thermal_policy_dev = ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO;4795 4796 err = fan_boost_mode_check_present(asus);4797 if (err)4798 goto fail_fan_boost_mode;4799 4800 err = platform_profile_setup(asus);4801 if (err)4802 goto fail_platform_profile_setup;4803 4804 err = asus_wmi_sysfs_init(asus->platform_device);4805 if (err)4806 goto fail_sysfs;4807 4808 err = asus_wmi_input_init(asus);4809 if (err)4810 goto fail_input;4811 4812 err = asus_wmi_fan_init(asus); /* probably no problems on error */4813 4814 err = asus_wmi_hwmon_init(asus);4815 if (err)4816 goto fail_hwmon;4817 4818 err = asus_wmi_custom_fan_curve_init(asus);4819 if (err)4820 goto fail_custom_fan_curve;4821 4822 err = asus_wmi_led_init(asus);4823 if (err)4824 goto fail_leds;4825 4826 asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_WLAN, &result);4827 if (result & (ASUS_WMI_DSTS_PRESENCE_BIT | ASUS_WMI_DSTS_USER_BIT))4828 asus->driver->wlan_ctrl_by_user = 1;4829 4830 if (!(asus->driver->wlan_ctrl_by_user && ashs_present())) {4831 err = asus_wmi_rfkill_init(asus);4832 if (err)4833 goto fail_rfkill;4834 }4835 4836 if (asus->driver->quirks->wmi_force_als_set)4837 asus_wmi_set_als();4838 4839 if (asus->driver->quirks->xusb2pr)4840 asus_wmi_set_xusb2pr(asus);4841 4842 if (acpi_video_get_backlight_type() == acpi_backlight_vendor) {4843 err = asus_wmi_backlight_init(asus);4844 if (err && err != -ENODEV)4845 goto fail_backlight;4846 } else if (asus->driver->quirks->wmi_backlight_set_devstate)4847 err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BACKLIGHT, 2, NULL);4848 4849 if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_SCREENPAD_LIGHT)) {4850 err = asus_screenpad_init(asus);4851 if (err && err != -ENODEV)4852 goto fail_screenpad;4853 }4854 4855 if (asus_wmi_has_fnlock_key(asus)) {4856 asus->fnlock_locked = fnlock_default;4857 asus_wmi_fnlock_update(asus);4858 }4859 4860 status = wmi_install_notify_handler(asus->driver->event_guid,4861 asus_wmi_notify, asus);4862 if (ACPI_FAILURE(status)) {4863 pr_err("Unable to register notify handler - %d\n", status);4864 err = -ENODEV;4865 goto fail_wmi_handler;4866 }4867 4868 if (asus->driver->i8042_filter) {4869 err = i8042_install_filter(asus->driver->i8042_filter);4870 if (err)4871 pr_warn("Unable to install key filter - %d\n", err);4872 }4873 4874 asus_wmi_battery_init(asus);4875 4876 asus_wmi_debugfs_init(asus);4877 4878 return 0;4879 4880fail_wmi_handler:4881 asus_wmi_backlight_exit(asus);4882fail_backlight:4883 asus_wmi_rfkill_exit(asus);4884fail_screenpad:4885 asus_screenpad_exit(asus);4886fail_rfkill:4887 asus_wmi_led_exit(asus);4888fail_leds:4889fail_hwmon:4890 asus_wmi_input_exit(asus);4891fail_input:4892 asus_wmi_sysfs_exit(asus->platform_device);4893fail_sysfs:4894fail_custom_fan_curve:4895fail_platform_profile_setup:4896 if (asus->platform_profile_support)4897 platform_profile_remove();4898fail_fan_boost_mode:4899fail_platform:4900 kfree(asus);4901 return err;4902}4903 4904static void asus_wmi_remove(struct platform_device *device)4905{4906 struct asus_wmi *asus;4907 4908 asus = platform_get_drvdata(device);4909 if (asus->driver->i8042_filter)4910 i8042_remove_filter(asus->driver->i8042_filter);4911 wmi_remove_notify_handler(asus->driver->event_guid);4912 asus_wmi_backlight_exit(asus);4913 asus_screenpad_exit(asus);4914 asus_wmi_input_exit(asus);4915 asus_wmi_led_exit(asus);4916 asus_wmi_rfkill_exit(asus);4917 asus_wmi_debugfs_exit(asus);4918 asus_wmi_sysfs_exit(asus->platform_device);4919 asus_fan_set_auto(asus);4920 throttle_thermal_policy_set_default(asus);4921 asus_wmi_battery_exit(asus);4922 4923 if (asus->platform_profile_support)4924 platform_profile_remove();4925 4926 kfree(asus);4927}4928 4929/* Platform driver - hibernate/resume callbacks *******************************/4930 4931static int asus_hotk_thaw(struct device *device)4932{4933 struct asus_wmi *asus = dev_get_drvdata(device);4934 4935 if (asus->wlan.rfkill) {4936 bool wlan;4937 4938 /*4939 * Work around bios bug - acpi _PTS turns off the wireless led4940 * during suspend. Normally it restores it on resume, but4941 * we should kick it ourselves in case hibernation is aborted.4942 */4943 wlan = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WLAN);4944 asus_wmi_set_devstate(ASUS_WMI_DEVID_WLAN, wlan, NULL);4945 }4946 4947 return 0;4948}4949 4950static int asus_hotk_resume(struct device *device)4951{4952 struct asus_wmi *asus = dev_get_drvdata(device);4953 4954 if (!IS_ERR_OR_NULL(asus->kbd_led.dev))4955 kbd_led_update(asus);4956 4957 if (asus_wmi_has_fnlock_key(asus))4958 asus_wmi_fnlock_update(asus);4959 4960 asus_wmi_tablet_mode_get_state(asus);4961 4962 return 0;4963}4964 4965static int asus_hotk_resume_early(struct device *device)4966{4967 struct asus_wmi *asus = dev_get_drvdata(device);4968 4969 if (asus->ally_mcu_usb_switch) {4970 /* sleep required to prevent USB0 being yanked then reappearing rapidly */4971 if (ACPI_FAILURE(acpi_execute_simple_method(NULL, ASUS_USB0_PWR_EC0_CSEE, 0xB8)))4972 dev_err(device, "ROG Ally MCU failed to connect USB dev\n");4973 else4974 msleep(ASUS_USB0_PWR_EC0_CSEE_WAIT);4975 }4976 return 0;4977}4978 4979static int asus_hotk_prepare(struct device *device)4980{4981 struct asus_wmi *asus = dev_get_drvdata(device);4982 4983 if (asus->ally_mcu_usb_switch) {4984 /* sleep required to ensure USB0 is disabled before sleep continues */4985 if (ACPI_FAILURE(acpi_execute_simple_method(NULL, ASUS_USB0_PWR_EC0_CSEE, 0xB7)))4986 dev_err(device, "ROG Ally MCU failed to disconnect USB dev\n");4987 else4988 msleep(ASUS_USB0_PWR_EC0_CSEE_WAIT);4989 }4990 return 0;4991}4992 4993static int asus_hotk_restore(struct device *device)4994{4995 struct asus_wmi *asus = dev_get_drvdata(device);4996 int bl;4997 4998 /* Refresh both wlan rfkill state and pci hotplug */4999 if (asus->wlan.rfkill)5000 asus_rfkill_hotplug(asus);5001 5002 if (asus->bluetooth.rfkill) {5003 bl = !asus_wmi_get_devstate_simple(asus,5004 ASUS_WMI_DEVID_BLUETOOTH);5005 rfkill_set_sw_state(asus->bluetooth.rfkill, bl);5006 }5007 if (asus->wimax.rfkill) {5008 bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WIMAX);5009 rfkill_set_sw_state(asus->wimax.rfkill, bl);5010 }5011 if (asus->wwan3g.rfkill) {5012 bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WWAN3G);5013 rfkill_set_sw_state(asus->wwan3g.rfkill, bl);5014 }5015 if (asus->gps.rfkill) {5016 bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_GPS);5017 rfkill_set_sw_state(asus->gps.rfkill, bl);5018 }5019 if (asus->uwb.rfkill) {5020 bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_UWB);5021 rfkill_set_sw_state(asus->uwb.rfkill, bl);5022 }5023 if (!IS_ERR_OR_NULL(asus->kbd_led.dev))5024 kbd_led_update(asus);5025 5026 if (asus_wmi_has_fnlock_key(asus))5027 asus_wmi_fnlock_update(asus);5028 5029 asus_wmi_tablet_mode_get_state(asus);5030 return 0;5031}5032 5033static const struct dev_pm_ops asus_pm_ops = {5034 .thaw = asus_hotk_thaw,5035 .restore = asus_hotk_restore,5036 .resume = asus_hotk_resume,5037 .resume_early = asus_hotk_resume_early,5038 .prepare = asus_hotk_prepare,5039};5040 5041/* Registration ***************************************************************/5042 5043static int asus_wmi_probe(struct platform_device *pdev)5044{5045 struct platform_driver *pdrv = to_platform_driver(pdev->dev.driver);5046 struct asus_wmi_driver *wdrv = to_asus_wmi_driver(pdrv);5047 int ret;5048 5049 if (!wmi_has_guid(ASUS_WMI_MGMT_GUID)) {5050 pr_warn("ASUS Management GUID not found\n");5051 return -ENODEV;5052 }5053 5054 if (wdrv->event_guid && !wmi_has_guid(wdrv->event_guid)) {5055 pr_warn("ASUS Event GUID not found\n");5056 return -ENODEV;5057 }5058 5059 if (wdrv->probe) {5060 ret = wdrv->probe(pdev);5061 if (ret)5062 return ret;5063 }5064 5065 return asus_wmi_add(pdev);5066}5067 5068static bool used;5069 5070int __init_or_module asus_wmi_register_driver(struct asus_wmi_driver *driver)5071{5072 struct platform_driver *platform_driver;5073 struct platform_device *platform_device;5074 5075 if (used)5076 return -EBUSY;5077 5078 platform_driver = &driver->platform_driver;5079 platform_driver->remove_new = asus_wmi_remove;5080 platform_driver->driver.owner = driver->owner;5081 platform_driver->driver.name = driver->name;5082 platform_driver->driver.pm = &asus_pm_ops;5083 5084 platform_device = platform_create_bundle(platform_driver,5085 asus_wmi_probe,5086 NULL, 0, NULL, 0);5087 if (IS_ERR(platform_device))5088 return PTR_ERR(platform_device);5089 5090 used = true;5091 return 0;5092}5093EXPORT_SYMBOL_GPL(asus_wmi_register_driver);5094 5095void asus_wmi_unregister_driver(struct asus_wmi_driver *driver)5096{5097 platform_device_unregister(driver->platform_device);5098 platform_driver_unregister(&driver->platform_driver);5099 used = false;5100}5101EXPORT_SYMBOL_GPL(asus_wmi_unregister_driver);5102 5103static int __init asus_wmi_init(void)5104{5105 pr_info("ASUS WMI generic driver loaded\n");5106 return 0;5107}5108 5109static void __exit asus_wmi_exit(void)5110{5111 pr_info("ASUS WMI generic driver unloaded\n");5112}5113 5114module_init(asus_wmi_init);5115module_exit(asus_wmi_exit);5116