diff --git a/Documentation/wmi/devices/bitland-mifs-wmi.rst b/Documentation/wmi/devices/bitland-mifs-wmi.rst index 9e86ecc2993c..314b3fbdda45 100644 --- a/Documentation/wmi/devices/bitland-mifs-wmi.rst +++ b/Documentation/wmi/devices/bitland-mifs-wmi.rst @@ -67,7 +67,7 @@ WMI Methods (MICommonInterface) The ``MICommonInterface`` class (GUID: ``{b60bfb48-3e5b-49e4-a0e9-8cffe1b3434b}``) is the primary control interface. It uses a 32-byte buffer for both input -(``InData``) and output (``OutData``). +(``InData``) and output (``OutData`` + ``Reserved``). Method Structure ---------------- @@ -77,53 +77,78 @@ The data packet follows a standardized format: +----------+------------------------------------------------------------------+ | Byte | Description | +==========+==================================================================+ -| 1 | Method Type: Get (0xFA / 250) or Set (0xFB / 251) | +| 1 and 2 | Method Type or Return Code | +----------+------------------------------------------------------------------+ -| 3 | Command ID (Method Name) | +| 3 and 4 | Command ID (Method Name) | +----------+------------------------------------------------------------------+ -| 4 - 31 | Arguments (for Set) or Return Data (for Get) | +| 5 - 32 | Arguments (for Set) or Return Data (for Get) | +----------+------------------------------------------------------------------+ +Method Types +------------ + +The following Method types are understood by the underlying firmware: + ++--------+---------+ +| Type | Meaning | ++========+=========+ +| 0xFA00 | Read | ++--------+---------+ +| 0xFB00 | Write | ++--------+---------+ + +Return Codes +------------ + +The following Return Codes are know to be returned in response to a WMI method invocation: + ++--------+--------------------+ +| Code | Meaning | ++========+====================+ +| 0x8000 | Success | ++--------+--------------------+ +| 0xE000 | Invalid Command ID | ++--------+--------------------+ Command IDs ----------- -The following Command IDs are used in the third byte of the buffer: +The following Command IDs know to be used on some models: +----------+-----------------------+------------------------------------------+ | ID | Name | Values / Description | +==========+=======================+==========================================+ -| 8 | SystemPerMode | 0: Balance, 1: Performance, 2: Quiet, | +| 0x0800 | SystemPerMode | 0: Balance, 1: Performance, 2: Quiet, | | | | 3: Full-speed | +----------+-----------------------+------------------------------------------+ -| 9 | GPUMode | 0: Hybrid, 1: Discrete, 2: UMA | +| 0x0900 | GPUMode | 0: Hybrid, 1: Discrete, 2: UMA | +----------+-----------------------+------------------------------------------+ -| 10 | KeyboardType | 0: White, 1: Single RGB, 2: Zone RGB | +| 0x0A00 | KeyboardType | 0: White, 1: Single RGB, 2: Zone RGB | +----------+-----------------------+------------------------------------------+ -| 11 | FnLock | 0: Off, 1: On | +| 0x0B00 | FnLock | 0: Off, 1: On | +----------+-----------------------+------------------------------------------+ -| 12 | TPLock | 0: Unlock, 1: Lock (Touchpad) | +| 0x0C00 | TPLock | 0: Unlock, 1: Lock (Touchpad) | +----------+-----------------------+------------------------------------------+ -| 13 | CPUGPUSYSFanSpeed | Returns 12 bytes of fan data: | +| 0x0D00 | CPUGPUSYSFanSpeed | Returns 12 bytes of fan data: | | | | Bytes 4-5: CPU Fan RPM (Little Endian) | | | | Bytes 6-7: GPU Fan RPM (Little Endian) | | | | Bytes 10-11: SYS Fan RPM (Little Endian) | +----------+-----------------------+------------------------------------------+ -| 16 | RGBKeyboardMode | 0: Off, 1: Auto Cyclic, 2: Fixed, | +| 0x1000 | RGBKeyboardMode | 0: Off, 1: Auto Cyclic, 2: Fixed, | | | | 3: Custom | +----------+-----------------------+------------------------------------------+ -| 17 | RGBKeyboardColor | Bytes 4, 5, 6: Red, Green, Blue values | +| 0x1100 | RGBKeyboardColor | Bytes 4, 5, 6: Red, Green, Blue values | +----------+-----------------------+------------------------------------------+ -| 18 | RGBKeyboardBrightness | 0-10: Brightness Levels, 128: Auto | +| 0x1200 | RGBKeyboardBrightness | 0-10: Brightness Levels, 128: Auto | +----------+-----------------------+------------------------------------------+ -| 19 | SystemAcType | 1: Type-C, 2: Circular Hole (DC) | +| 0x1300 | SystemAcType | 1: Type-C, 2: Circular Hole (DC) | +----------+-----------------------+------------------------------------------+ -| 20 | MaxFanSpeedSwitch | Byte 4: Fan Type (0: CPU/GPU, 1: SYS) | +| 0x1400 | MaxFanSpeedSwitch | Byte 4: Fan Type (0: CPU/GPU, 1: SYS) | | | | Byte 5: State (0: Off, 1: On) | +----------+-----------------------+------------------------------------------+ -| 21 | MaxFanSpeed | Sets manual fan speed duty cycle | +| 0x1500 | MaxFanSpeed | Sets manual fan speed duty cycle | +----------+-----------------------+------------------------------------------+ -| 22 | CPUThermometer | Returns CPU Temperature | +| 0x1600 | CPUThermometer | Returns CPU Temperature | +----------+-----------------------+------------------------------------------+ WMI Events (HID_EVENT20) diff --git a/drivers/platform/x86/bitland-mifs-wmi.c b/drivers/platform/x86/bitland-mifs-wmi.c index 3a373184519d..cdb930eb678d 100644 --- a/drivers/platform/x86/bitland-mifs-wmi.c +++ b/drivers/platform/x86/bitland-mifs-wmi.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -39,25 +40,30 @@ #define BITLAND_EVENT_GUID "46C93E13-EE9B-4262-8488-563BCA757FEF" enum bitland_mifs_operation { - WMI_METHOD_GET = 250, - WMI_METHOD_SET = 251, + WMI_METHOD_GET = 0xFA00, + WMI_METHOD_SET = 0xFB00, }; enum bitland_mifs_function { - WMI_FN_SYSTEM_PER_MODE = 8, - WMI_FN_GPU_MODE = 9, - WMI_FN_KBD_TYPE = 10, - WMI_FN_FN_LOCK = 11, - WMI_FN_TP_LOCK = 12, - WMI_FN_FAN_SPEEDS = 13, - WMI_FN_RGB_KB_MODE = 16, - WMI_FN_RGB_KB_COLOR = 17, - WMI_FN_RGB_KB_BRIGHTNESS = 18, - WMI_FN_SYSTEM_AC_TYPE = 19, - WMI_FN_MAX_FAN_SWITCH = 20, - WMI_FN_MAX_FAN_SPEED = 21, - WMI_FN_CPU_THERMOMETER = 22, - WMI_FN_CPU_POWER = 23, + WMI_FN_SYSTEM_PER_MODE = 0x0800, + WMI_FN_GPU_MODE = 0x0900, + WMI_FN_KBD_TYPE = 0x0A00, + WMI_FN_FN_LOCK = 0x0B00, + WMI_FN_TP_LOCK = 0x0C00, + WMI_FN_FAN_SPEEDS = 0x0D00, + WMI_FN_RGB_KB_MODE = 0x1000, + WMI_FN_RGB_KB_COLOR = 0x1100, + WMI_FN_RGB_KB_BRIGHTNESS = 0x1200, + WMI_FN_SYSTEM_AC_TYPE = 0x1300, + WMI_FN_MAX_FAN_SWITCH = 0x1400, + WMI_FN_MAX_FAN_SPEED = 0x1500, + WMI_FN_CPU_THERMOMETER = 0x1600, + WMI_FN_CPU_POWER = 0x1700, +}; + +enum bitland_mifs_return_code { + WMI_RETURN_CODE_SUCCESS = 0x8000, + WMI_RETURN_CODE_UNKNOWN_FUNCTION = 0xE000, }; enum bitland_system_ac_mode { @@ -114,18 +120,14 @@ enum bitland_wmi_device_type { }; struct bitland_mifs_input { - u8 reserved1; - u8 operation; - u8 reserved2; - u8 function; + __le16 operation; + __le16 function; u8 payload[28]; } __packed; struct bitland_mifs_output { - u8 reserved1; - u8 operation; - u8 reserved2; - u8 function; + __le16 return_code; + __le16 function; u8 data[28]; } __packed; @@ -171,15 +173,27 @@ static int bitland_mifs_wmi_call(struct bitland_mifs_wmi_data *data, guard(mutex)(&data->lock); - if (!output) - return wmidev_invoke_procedure(data->wdev, 0, 1, &in_buf); - - ret = wmidev_invoke_method(data->wdev, 0, 1, &in_buf, &out_buf, sizeof(*output)); + ret = wmidev_invoke_method(data->wdev, 0, 1, &in_buf, &out_buf, + sizeof(struct bitland_mifs_output)); if (ret) return ret; - memcpy(output, out_buf.data, sizeof(*output)); - kfree(out_buf.data); + struct bitland_mifs_output *result __free(kfree) = out_buf.data; + + switch (le16_to_cpu(result->return_code)) { + case WMI_RETURN_CODE_SUCCESS: + break; + case WMI_RETURN_CODE_UNKNOWN_FUNCTION: + return -EOPNOTSUPP; + default: + return -EIO; + } + + if (result->function != input->function) + return -ENOMSG; + + if (output) + memcpy(output, result, sizeof(*output)); return 0; } @@ -189,10 +203,8 @@ static int laptop_profile_get(struct device *dev, { struct bitland_mifs_wmi_data *data = dev_get_drvdata(dev); struct bitland_mifs_input input = { - .reserved1 = 0, - .operation = WMI_METHOD_GET, - .reserved2 = 0, - .function = WMI_FN_SYSTEM_PER_MODE, + .operation = cpu_to_le16(WMI_METHOD_GET), + .function = cpu_to_le16(WMI_FN_SYSTEM_PER_MODE), }; struct bitland_mifs_output result; int ret; @@ -223,8 +235,8 @@ static int laptop_profile_get(struct device *dev, static int bitland_check_performance_capability(struct bitland_mifs_wmi_data *data) { struct bitland_mifs_input input = { - .operation = WMI_METHOD_GET, - .function = WMI_FN_SYSTEM_AC_TYPE, + .operation = cpu_to_le16(WMI_METHOD_GET), + .function = cpu_to_le16(WMI_FN_SYSTEM_AC_TYPE), }; struct bitland_mifs_output output; int ret; @@ -248,10 +260,8 @@ static int laptop_profile_set(struct device *dev, { struct bitland_mifs_wmi_data *data = dev_get_drvdata(dev); struct bitland_mifs_input input = { - .reserved1 = 0, - .operation = WMI_METHOD_SET, - .reserved2 = 0, - .function = WMI_FN_SYSTEM_PER_MODE, + .operation = cpu_to_le16(WMI_METHOD_SET), + .function = cpu_to_le16(WMI_FN_SYSTEM_PER_MODE), }; int ret; u8 val; @@ -344,22 +354,20 @@ static int laptop_hwmon_read(struct device *dev, enum hwmon_sensor_types type, { struct bitland_mifs_wmi_data *data = dev_get_drvdata(dev); struct bitland_mifs_input input = { - .reserved1 = 0, - .operation = WMI_METHOD_GET, - .reserved2 = 0, + .operation = cpu_to_le16(WMI_METHOD_GET), }; struct bitland_mifs_output res; int ret; switch (type) { case hwmon_temp: - input.function = WMI_FN_CPU_THERMOMETER; + input.function = cpu_to_le16(WMI_FN_CPU_THERMOMETER); ret = bitland_mifs_wmi_call(data, &input, &res); if (!ret) *val = res.data[0] * MILLIDEGREE_PER_DEGREE; return ret; case hwmon_fan: - input.function = WMI_FN_FAN_SPEEDS; + input.function = cpu_to_le16(WMI_FN_FAN_SPEEDS); ret = bitland_mifs_wmi_call(data, &input, &res); if (ret) return ret; @@ -420,10 +428,8 @@ static int laptop_kbd_led_set(struct led_classdev *led_cdev, struct bitland_mifs_wmi_data *data = container_of(led_cdev, struct bitland_mifs_wmi_data, kbd_led); struct bitland_mifs_input input = { - .reserved1 = 0, - .operation = WMI_METHOD_SET, - .reserved2 = 0, - .function = WMI_FN_RGB_KB_BRIGHTNESS, + .operation = cpu_to_le16(WMI_METHOD_SET), + .function = cpu_to_le16(WMI_FN_RGB_KB_BRIGHTNESS), }; input.payload[0] = (u8)value; @@ -436,10 +442,8 @@ static enum led_brightness laptop_kbd_led_get(struct led_classdev *led_cdev) struct bitland_mifs_wmi_data *data = container_of(led_cdev, struct bitland_mifs_wmi_data, kbd_led); struct bitland_mifs_input input = { - .reserved1 = 0, - .operation = WMI_METHOD_GET, - .reserved2 = 0, - .function = WMI_FN_RGB_KB_BRIGHTNESS, + .operation = cpu_to_le16(WMI_METHOD_GET), + .function = cpu_to_le16(WMI_FN_RGB_KB_BRIGHTNESS), }; struct bitland_mifs_output res; int ret; @@ -463,10 +467,8 @@ static ssize_t gpu_mode_show(struct device *dev, struct device_attribute *attr, { struct bitland_mifs_wmi_data *data = dev_get_drvdata(dev); struct bitland_mifs_input input = { - .reserved1 = 0, - .operation = WMI_METHOD_GET, - .reserved2 = 0, - .function = WMI_FN_GPU_MODE, + .operation = cpu_to_le16(WMI_METHOD_GET), + .function = cpu_to_le16(WMI_FN_GPU_MODE), }; struct bitland_mifs_output res; u8 mode_val; @@ -488,10 +490,8 @@ static ssize_t gpu_mode_store(struct device *dev, struct device_attribute *attr, { struct bitland_mifs_wmi_data *data = dev_get_drvdata(dev); struct bitland_mifs_input input = { - .reserved1 = 0, - .operation = WMI_METHOD_SET, - .reserved2 = 0, - .function = WMI_FN_GPU_MODE, + .operation = cpu_to_le16(WMI_METHOD_SET), + .function = cpu_to_le16(WMI_FN_GPU_MODE), }; int val; int ret; @@ -521,10 +521,8 @@ static ssize_t kb_mode_show(struct device *dev, struct device_attribute *attr, { struct bitland_mifs_wmi_data *data = dev_get_drvdata(dev); struct bitland_mifs_input input = { - .reserved1 = 0, - .operation = WMI_METHOD_GET, - .reserved2 = 0, - .function = WMI_FN_RGB_KB_MODE, + .operation = cpu_to_le16(WMI_METHOD_GET), + .function = cpu_to_le16(WMI_FN_RGB_KB_MODE), }; struct bitland_mifs_output res; u8 mode_val; @@ -546,10 +544,8 @@ static ssize_t kb_mode_store(struct device *dev, struct device_attribute *attr, { struct bitland_mifs_wmi_data *data = dev_get_drvdata(dev); struct bitland_mifs_input input = { - .reserved1 = 0, - .operation = WMI_METHOD_SET, - .reserved2 = 0, - .function = WMI_FN_RGB_KB_MODE, + .operation = cpu_to_le16(WMI_METHOD_SET), + .function = cpu_to_le16(WMI_FN_RGB_KB_MODE), }; // the wmi value (0, 1, 2 or 3) int val; @@ -575,10 +571,8 @@ static ssize_t fan_boost_store(struct device *dev, { struct bitland_mifs_wmi_data *data = dev_get_drvdata(dev); struct bitland_mifs_input input = { - .reserved1 = 0, - .operation = WMI_METHOD_SET, - .reserved2 = 0, - .function = WMI_FN_MAX_FAN_SWITCH, + .operation = cpu_to_le16(WMI_METHOD_SET), + .function = cpu_to_le16(WMI_FN_MAX_FAN_SWITCH), }; bool val; int ret;